1// Copyright 2016 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package datastore_test
16
17import (
18	"fmt"
19	"log"
20	"time"
21
22	"cloud.google.com/go/datastore"
23	"golang.org/x/net/context"
24)
25
26type Task struct {
27	Type            string
28	Done            bool
29	Priority        int
30	Description     string `datastore:",noindex"`
31	PercentComplete float64
32	Created         time.Time
33	Tags            []string
34	Collaborators   []string
35}
36
37func ExampleNewIncompleteKey() {
38	ctx := context.Background()
39	// [START incomplete_key]
40	taskKey := datastore.NewIncompleteKey(ctx, "Task", nil)
41	// [END incomplete_key]
42	_ = taskKey // Use the task key for datastore operations.
43}
44
45func ExampleNewKey() {
46	ctx := context.Background()
47	// [START named_key]
48	taskKey := datastore.NewKey(ctx, "Task", "sampletask", 0, nil)
49	// [END named_key]
50	_ = taskKey // Use the task key for datastore operations.
51}
52
53func ExampleNewKey_withParent() {
54	ctx := context.Background()
55	// [START key_with_parent]
56	parentKey := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
57	taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, parentKey)
58	// [END key_with_parent]
59	_ = taskKey // Use the task key for datastore operations.
60}
61
62func ExampleNewKey_withMultipleParents() {
63	ctx := context.Background()
64	// [START key_with_multilevel_parent]
65	userKey := datastore.NewKey(ctx, "User", "alice", 0, nil)
66	parentKey := datastore.NewKey(ctx, "TaskList", "default", 0, userKey)
67	taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, parentKey)
68	// [END key_with_multilevel_parent]
69	_ = taskKey // Use the task key for datastore operations.
70}
71
72func ExampleClient_Put() {
73	ctx := context.Background()
74	client, _ := datastore.NewClient(ctx, "my-proj")
75	// [START entity_with_parent]
76	parentKey := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
77	key := datastore.NewIncompleteKey(ctx, "Task", parentKey)
78
79	task := Task{
80		Type:        "Personal",
81		Done:        false,
82		Priority:    4,
83		Description: "Learn Cloud Datastore",
84	}
85
86	// A complete key is assigned to the entity when it is Put.
87	var err error
88	key, err = client.Put(ctx, key, &task)
89	// [END entity_with_parent]
90	_ = err // Make sure you check err.
91}
92
93func Example_properties() {
94	// [START properties]
95	type Task struct {
96		Type            string
97		Done            bool
98		Priority        int
99		Description     string `datastore:",noindex"`
100		PercentComplete float64
101		Created         time.Time
102	}
103	task := &Task{
104		Type:            "Personal",
105		Done:            false,
106		Priority:        4,
107		Description:     "Learn Cloud Datastore",
108		PercentComplete: 10.0,
109		Created:         time.Now(),
110	}
111	// [END properties]
112	_ = task // Use the task in a datastore Put operation.
113}
114
115func Example_sliceProperties() {
116	// [START array_value]
117	type Task struct {
118		Tags          []string
119		Collaborators []string
120	}
121	task := &Task{
122		Tags:          []string{"fun", "programming"},
123		Collaborators: []string{"alice", "bob"},
124	}
125	// [END array_value]
126	_ = task // Use the task in a datastore Put operation.
127}
128
129func Example_basicEntity() {
130	// [START basic_entity]
131	type Task struct {
132		Type            string
133		Done            bool
134		Priority        float64
135		Description     string `datastore:",noindex"`
136		PercentComplete float64
137		Created         time.Time
138	}
139	task := &Task{
140		Type:            "Personal",
141		Done:            false,
142		Priority:        4,
143		Description:     "Learn Cloud Datastore",
144		PercentComplete: 10.0,
145		Created:         time.Now(),
146	}
147	// [END basic_entity]
148	_ = task // Use the task in a datastore Put operation.
149}
150
151func ExampleClient_Put_upsert() {
152	ctx := context.Background()
153	client, _ := datastore.NewClient(ctx, "my-proj")
154	task := &Task{} // Populated with appropriate data.
155	key := datastore.NewIncompleteKey(ctx, "Task", nil)
156	// [START upsert]
157	key, err := client.Put(ctx, key, task)
158	// [END upsert]
159	_ = err // Make sure you check err.
160	_ = key // key is the complete key for the newly stored task
161}
162
163func ExampleTransaction_insert() {
164	ctx := context.Background()
165	client, _ := datastore.NewClient(ctx, "my-proj")
166	task := &Task{} // Populated with appropriate data.
167	taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, nil)
168	// [START insert]
169	tx, err := client.NewTransaction(ctx)
170	if err != nil {
171		log.Fatalf("client.NewTransaction: %v", err)
172	}
173	// We first check that there is no entity stored with the given key.
174	if err := tx.Get(taskKey, nil); err != datastore.ErrNoSuchEntity {
175		log.Fatalf("tx.Get returned err %v, want ErrNoSuchEntity", err)
176	}
177	if _, err := tx.Put(taskKey, task); err != nil {
178		log.Fatalf("tx.Put: %v", err)
179	}
180	if _, err := tx.Commit(); err != nil {
181		log.Fatalf("tx.Commit: %v", err)
182	}
183	// [END insert]
184}
185
186func ExampleClient_Get() {
187	ctx := context.Background()
188	client, _ := datastore.NewClient(ctx, "my-proj")
189	taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, nil)
190	// [START lookup]
191	var task Task
192	err := client.Get(ctx, taskKey, &task)
193	// [END lookup]
194	_ = err // Make sure you check err.
195}
196
197func ExampleTransaction_update() {
198	ctx := context.Background()
199	client, _ := datastore.NewClient(ctx, "my-proj")
200	taskKey := datastore.NewKey(ctx, "Task", "sampleTask", 0, nil)
201	// [START update]
202	tx, err := client.NewTransaction(ctx)
203	if err != nil {
204		log.Fatalf("client.NewTransaction: %v", err)
205	}
206	var task Task
207	if err := tx.Get(taskKey, &task); err != nil {
208		log.Fatalf("tx.Get: %v", err)
209	}
210	task.Priority = 5
211	if _, err := tx.Put(taskKey, task); err != nil {
212		log.Fatalf("tx.Put: %v", err)
213	}
214	if _, err := tx.Commit(); err != nil {
215		log.Fatalf("tx.Commit: %v", err)
216	}
217	// [END update]
218}
219
220func ExampleClient_Delete() {
221	ctx := context.Background()
222	client, _ := datastore.NewClient(ctx, "my-proj")
223	key := datastore.NewKey(ctx, "Task", "sampletask", 0, nil)
224	// [START delete]
225	err := client.Delete(ctx, key)
226	// [END delete]
227	_ = err // Make sure you check err.
228}
229
230func ExampleClient_PutMulti() {
231	ctx := context.Background()
232	client, _ := datastore.NewClient(ctx, "my-proj")
233	// [START batch_upsert]
234	tasks := []*Task{
235		{
236			Type:        "Personal",
237			Done:        false,
238			Priority:    4,
239			Description: "Learn Cloud Datastore",
240		},
241		{
242			Type:        "Personal",
243			Done:        false,
244			Priority:    5,
245			Description: "Integrate Cloud Datastore",
246		},
247	}
248	keys := []*datastore.Key{
249		datastore.NewIncompleteKey(ctx, "Task", nil),
250		datastore.NewIncompleteKey(ctx, "Task", nil),
251	}
252
253	keys, err := client.PutMulti(ctx, keys, tasks)
254	// [END batch_upsert]
255	_ = err  // Make sure you check err.
256	_ = keys // keys now has the complete keys for the newly stored tasks.
257}
258
259func ExampleClient_GetMulti() {
260	ctx := context.Background()
261	client, _ := datastore.NewClient(ctx, "my-proj")
262	var taskKeys []*datastore.Key // Populated with incomplete keys.
263	// [START batch_lookup]
264	var tasks []*Task
265	err := client.GetMulti(ctx, taskKeys, &tasks)
266	// [END batch_lookup]
267	_ = err // Make sure you check err.
268}
269
270func ExampleClient_DeleteMulti() {
271	ctx := context.Background()
272	client, _ := datastore.NewClient(ctx, "my-proj")
273	var taskKeys []*datastore.Key // Populated with incomplete keys.
274	// [START batch_delete]
275	err := client.DeleteMulti(ctx, taskKeys)
276	// [END batch_delete]
277	_ = err // Make sure you check err.
278}
279
280func ExampleQuery_basic() {
281	ctx := context.Background()
282	client, _ := datastore.NewClient(ctx, "my-proj")
283	// [START basic_query]
284	query := datastore.NewQuery("Task").
285		Filter("Done =", false).
286		Filter("Priority >=", 4).
287		Order("-Priority")
288	// [END basic_query]
289	// [START run_query]
290	it := client.Run(ctx, query)
291	for {
292		var task Task
293		_, err := it.Next(&task)
294		if err == datastore.Done {
295			break
296		}
297		if err != nil {
298			log.Fatalf("Error fetching next task: %v", err)
299		}
300		fmt.Printf("Task %q, Priority %d\n", task.Description, task.Priority)
301	}
302	// [END run_query]
303}
304
305func ExampleQuery_propertyFilter() {
306	// [START property_filter]
307	query := datastore.NewQuery("Task").Filter("Done =", false)
308	// [END property_filter]
309	_ = query // Use client.Run or client.GetAll to execute the query.
310}
311
312func ExampleQuery_compositeFilter() {
313	// [START composite_filter]
314	query := datastore.NewQuery("Task").Filter("Done =", false).Filter("Priority =", 4)
315	// [END composite_filter]
316	_ = query // Use client.Run or client.GetAll to execute the query.
317}
318
319func ExampleQuery_keyFilter() {
320	ctx := context.Background()
321	// [START key_filter]
322	key := datastore.NewKey(ctx, "Task", "someTask", 0, nil)
323	query := datastore.NewQuery("Task").Filter("__key__ >", key)
324	// [END key_filter]
325	_ = query // Use client.Run or client.GetAll to execute the query.
326}
327
328func ExampleQuery_sortAscending() {
329	// [START ascending_sort]
330	query := datastore.NewQuery("Task").Order("created")
331	// [END ascending_sort]
332	_ = query // Use client.Run or client.GetAll to execute the query.
333}
334
335func ExampleQuery_sortDescending() {
336	// [START descending_sort]
337	query := datastore.NewQuery("Task").Order("-created")
338	// [END descending_sort]
339	_ = query // Use client.Run or client.GetAll to execute the query.
340}
341
342func ExampleQuery_sortMulti() {
343	// [START multi_sort]
344	query := datastore.NewQuery("Task").Order("-priority").Order("created")
345	// [END multi_sort]
346	_ = query // Use client.Run or client.GetAll to execute the query.
347}
348
349func ExampleQuery_kindless() {
350	var lastSeenKey *datastore.Key
351	// [START kindless_query]
352	query := datastore.NewQuery("").Filter("__key__ >", lastSeenKey)
353	// [END kindless_query]
354	_ = query // Use client.Run or client.GetAll to execute the query.
355}
356
357func ExampleQuery_Ancestor() {
358	ctx := context.Background()
359	// [START ancestor_query]
360	ancestor := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
361	query := datastore.NewQuery("Task").Ancestor(ancestor)
362	// [END ancestor_query]
363	_ = query // Use client.Run or client.GetAll to execute the query.
364}
365
366func ExampleQuery_Project() {
367	ctx := context.Background()
368	client, _ := datastore.NewClient(ctx, "my-proj")
369	// [START projection_query]
370	query := datastore.NewQuery("Task").Project("Priority", "PercentComplete")
371	// [END projection_query]
372	// [START run_query_projection]
373	var priorities []int
374	var percents []float64
375	it := client.Run(ctx, query)
376	for {
377		var task Task
378		if _, err := it.Next(&task); err == datastore.Done {
379			break
380		} else if err != nil {
381			log.Fatal(err)
382		}
383		priorities = append(priorities, task.Priority)
384		percents = append(percents, task.PercentComplete)
385	}
386	// [END run_query_projection]
387}
388
389func ExampleQuery_KeysOnly() {
390	ctx := context.Background()
391	client, _ := datastore.NewClient(ctx, "my-proj")
392	// [START keys_only_query]
393	query := datastore.NewQuery("Task").KeysOnly()
394	// [END keys_only_query]
395	// [START run_keys_only_query]
396	keys, err := client.GetAll(ctx, query, nil)
397	// [END run_keys_only_query]
398	_ = err  // Make sure you check err.
399	_ = keys // Keys contains keys for all stored tasks.
400}
401
402func ExampleQuery_Distinct() {
403	// [START distinct_query]
404	query := datastore.NewQuery("Task").
405		Project("Priority", "PercentComplete").
406		Distinct().
407		Order("Type").Order("Priority")
408	// [END distinct_query]
409	_ = query // Use client.Run or client.GetAll to execute the query.
410
411	// [START distinct_on_query]
412	// DISTINCT ON not supported in Go API
413	// [END distinct_on_query]
414}
415
416func ExampleQuery_Filter_arrayInequality() {
417	// [START array_value_inequality_range]
418	query := datastore.NewQuery("Task").
419		Filter("Tag >", "learn").
420		Filter("Tag <", "math")
421	// [END array_value_inequality_range]
422	_ = query // Use client.Run or client.GetAll to execute the query.
423}
424
425func ExampleQuery_Filter_arrayEquality() {
426	// [START array_value_equality]
427	query := datastore.NewQuery("Task").
428		Filter("Tag =", "fun").
429		Filter("Tag =", "programming")
430	// [END array_value_equality]
431	_ = query // Use client.Run or client.GetAll to execute the query.
432}
433
434func ExampleQuery_Filter_inequality() {
435	// [START inequality_range]
436	query := datastore.NewQuery("Task").
437		Filter("Created >", time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)).
438		Filter("Created <", time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC))
439	// [END inequality_range]
440	_ = query // Use client.Run or client.GetAll to execute the query.
441}
442
443func ExampleQuery_Filter_invalidInequality() {
444	// [START inequality_invalid]
445	query := datastore.NewQuery("Task").
446		Filter("Created >", time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)).
447		Filter("Priority >", 3)
448	// [END inequality_invalid]
449	_ = query // The query is invalid.
450}
451
452func ExampleQuery_Filter_mixed() {
453	// [START equal_and_inequality_range]
454	query := datastore.NewQuery("Task").
455		Filter("Priority =", 4).
456		Filter("Done =", false).
457		Filter("Created >", time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC)).
458		Filter("Created <", time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC))
459	// [END equal_and_inequality_range]
460	_ = query // Use client.Run or client.GetAll to execute the query.
461}
462
463func ExampleQuery_inequalitySort() {
464	// [START inequality_sort]
465	query := datastore.NewQuery("Task").
466		Filter("Priority >", 3).
467		Order("Priority").
468		Order("Created")
469	// [END inequality_sort]
470	_ = query // Use client.Run or client.GetAll to execute the query.
471}
472
473func ExampleQuery_invalidInequalitySortA() {
474	// [START inequality_sort_invalid_not_same]
475	query := datastore.NewQuery("Task").
476		Filter("Priority >", 3).
477		Order("Created")
478	// [END inequality_sort_invalid_not_same]
479	_ = query // The query is invalid.
480}
481
482func ExampleQuery_invalidInequalitySortB() {
483	// [START inequality_sort_invalid_not_first]
484	query := datastore.NewQuery("Task").
485		Filter("Priority >", 3).
486		Order("Created").
487		Order("Priority")
488	// [END inequality_sort_invalid_not_first]
489	_ = query // The query is invalid.
490}
491
492func ExampleQuery_Limit() {
493	// [START limit]
494	query := datastore.NewQuery("Task").Limit(5)
495	// [END limit]
496	_ = query // Use client.Run or client.GetAll to execute the query.
497}
498
499func ExampleIterator_Cursor() {
500	ctx := context.Background()
501	client, _ := datastore.NewClient(ctx, "my-proj")
502	cursorStr := ""
503	// [START cursor_paging]
504	const pageSize = 5
505	query := datastore.NewQuery("Tasks").Limit(pageSize)
506	if cursorStr != "" {
507		cursor, err := datastore.DecodeCursor(cursorStr)
508		if err != nil {
509			log.Fatalf("Bad cursor %q: %v", cursorStr, err)
510		}
511		query = query.Start(cursor)
512	}
513
514	// Read the tasks.
515	var tasks []Task
516	var task Task
517	it := client.Run(ctx, query)
518	_, err := it.Next(&task)
519	for err == nil {
520		tasks = append(tasks, task)
521		_, err = it.Next(&task)
522	}
523	if err != datastore.Done {
524		log.Fatalf("Failed fetching results: %v", err)
525	}
526
527	// Get the cursor for the next page of results.
528	nextCursor, err := it.Cursor()
529	// [END cursor_paging]
530	_ = err        // Check the error.
531	_ = nextCursor // Use nextCursor.String as the next page's token.
532}
533
534func ExampleQuery_EventualConsistency() {
535	ctx := context.Background()
536	// [START eventual_consistent_query]
537	ancestor := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
538	query := datastore.NewQuery("Task").Ancestor(ancestor).EventualConsistency()
539	// [END eventual_consistent_query]
540	_ = query // Use client.Run or client.GetAll to execute the query.
541}
542
543func ExampleQuery_unindexed() {
544	// [START unindexed_property_query]
545	query := datastore.NewQuery("Tasks").Filter("Description =", "A task description")
546	// [END unindexed_property_query]
547	_ = query // Use client.Run or client.GetAll to execute the query.
548}
549
550func Example_explodingProperties() {
551	// [START exploding_properties]
552	task := &Task{
553		Tags:          []string{"fun", "programming", "learn"},
554		Collaborators: []string{"alice", "bob", "charlie"},
555		Created:       time.Now(),
556	}
557	// [END exploding_properties]
558	_ = task // Use the task in a datastore Put operation.
559}
560
561func Example_Transaction() {
562	ctx := context.Background()
563	client, _ := datastore.NewClient(ctx, "my-proj")
564	var to, from *datastore.Key
565	// [START transactional_update]
566	type BankAccount struct {
567		Balance int
568	}
569
570	const amount = 50
571	keys := []*datastore.Key{to, from}
572	tx, err := client.NewTransaction(ctx)
573	if err != nil {
574		log.Fatalf("client.NewTransaction: %v", err)
575	}
576	accs := make([]BankAccount, 2)
577	if err := tx.GetMulti(keys, accs); err != nil {
578		tx.Rollback()
579		log.Fatalf("tx.GetMulti: %v", err)
580	}
581	accs[0].Balance += amount
582	accs[1].Balance -= amount
583	if _, err := tx.PutMulti(keys, accs); err != nil {
584		tx.Rollback()
585		log.Fatalf("tx.PutMulti: %v", err)
586	}
587	if _, err = tx.Commit(); err != nil {
588		log.Fatalf("tx.Commit: %v", err)
589	}
590	// [END transactional_update]
591}
592
593func Example_Client_RunInTransaction() {
594	ctx := context.Background()
595	client, _ := datastore.NewClient(ctx, "my-proj")
596	var to, from *datastore.Key
597	// [START transactional_retry]
598	type BankAccount struct {
599		Balance int
600	}
601
602	const amount = 50
603	_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
604		keys := []*datastore.Key{to, from}
605		accs := make([]BankAccount, 2)
606		if err := tx.GetMulti(keys, accs); err != nil {
607			return err
608		}
609		accs[0].Balance += amount
610		accs[1].Balance -= amount
611		_, err := tx.PutMulti(keys, accs)
612		return err
613	})
614	// [END transactional_retry]
615	_ = err // Check error.
616}
617
618func ExampleTransaction_getOrCreate() {
619	ctx := context.Background()
620	client, _ := datastore.NewClient(ctx, "my-proj")
621	key := datastore.NewKey(ctx, "Task", "sampletask", 0, nil)
622	// [START transactional_get_or_create]
623	_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
624		var task Task
625		if err := tx.Get(key, &task); err != datastore.ErrNoSuchEntity {
626			return err
627		}
628		_, err := tx.Put(key, &Task{
629			Type:        "Personal",
630			Done:        false,
631			Priority:    4,
632			Description: "Learn Cloud Datastore",
633		})
634		return err
635	})
636	// [END transactional_get_or_create]
637	_ = err // Check error.
638}
639
640func ExampleTransaction_runQuery() {
641	ctx := context.Background()
642	client, _ := datastore.NewClient(ctx, "my-proj")
643	// [START transactional_single_entity_group_read_only]
644	tx, err := client.NewTransaction(ctx)
645	if err != nil {
646		log.Fatalf("client.NewTransaction: %v", err)
647	}
648	defer tx.Rollback() // Transaction only used for read.
649
650	ancestor := datastore.NewKey(ctx, "TaskList", "default", 0, nil)
651	query := datastore.NewQuery("Task").Ancestor(ancestor).Transaction(tx)
652	var tasks []Task
653	_, err = client.GetAll(ctx, query, &tasks)
654	// [END transactional_single_entity_group_read_only]
655	_ = err // Check error.
656}
657
658func Example_metadataNamespaces() {
659	ctx := context.Background()
660	client, _ := datastore.NewClient(ctx, "my-proj")
661	// [START namespace_run_query]
662	const (
663		startNamespace = "g"
664		endNamespace   = "h"
665	)
666	query := datastore.NewQuery("__namespace__").
667		Filter("__key__ >=", startNamespace).
668		Filter("__key__ <", endNamespace).
669		KeysOnly()
670	keys, err := client.GetAll(ctx, query, nil)
671	if err != nil {
672		log.Fatalf("client.GetAll: %v", err)
673	}
674
675	namespaces := make([]string, 0, len(keys))
676	for _, k := range keys {
677		namespaces = append(namespaces, k.Name())
678	}
679	// [END namespace_run_query]
680}
681
682func Example_metadataKinds() {
683	ctx := context.Background()
684	client, _ := datastore.NewClient(ctx, "my-proj")
685	// [START kind_run_query]
686	query := datastore.NewQuery("__kind__").KeysOnly()
687	keys, err := client.GetAll(ctx, query, nil)
688	if err != nil {
689		log.Fatalf("client.GetAll: %v", err)
690	}
691
692	kinds := make([]string, 0, len(keys))
693	for _, k := range keys {
694		kinds = append(kinds, k.Name())
695	}
696	// [END kind_run_query]
697}
698
699func Example_metadataProperties() {
700	ctx := context.Background()
701	client, _ := datastore.NewClient(ctx, "my-proj")
702	// [START property_run_query]
703	query := datastore.NewQuery("__property__").KeysOnly()
704	keys, err := client.GetAll(ctx, query, nil)
705	if err != nil {
706		log.Fatalf("client.GetAll: %v", err)
707	}
708
709	props := make(map[string][]string) // Map from kind to slice of properties.
710	for _, k := range keys {
711		prop := k.Name()
712		kind := k.Parent().Name()
713		props[kind] = append(props[kind], prop)
714	}
715	// [END property_run_query]
716}
717
718func Example_metadataPropertiesForKind() {
719	ctx := context.Background()
720	client, _ := datastore.NewClient(ctx, "my-proj")
721	// [START property_by_kind_run_query]
722	kindKey := datastore.NewKey(ctx, "__kind__", "Task", 0, nil)
723	query := datastore.NewQuery("__property__").Ancestor(kindKey)
724
725	type Prop struct {
726		Repr []string `datastore:"property_representation"`
727	}
728
729	var props []Prop
730	keys, err := client.GetAll(ctx, query, &props)
731	// [END property_by_kind_run_query]
732	_ = err  // Check error.
733	_ = keys // Use keys to find property names, and props for their representations.
734}
735