forked from googleapis/google-cloud-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
doc.go
216 lines (166 loc) · 6.29 KB
/
doc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// DO NOT EDIT doc.go. Modify internal/doc.template, then run make -C internal.
/*
Package firestore provides a client for reading and writing to a Cloud Firestore
database.
See https://cloud.google.com/firestore/docs for an introduction
to Cloud Firestore and additional help on using the Firestore API.
See https://godoc.org/cloud.google.com/go for authentication, timeouts,
connection pooling and similar aspects of this package.
Note: you can't use both Cloud Firestore and Cloud Datastore in the same
project.
Creating a Client
To start working with this package, create a client with a project ID:
ctx := context.Background()
client, err := firestore.NewClient(ctx, "projectID")
if err != nil {
// TODO: Handle error.
}
CollectionRefs and DocumentRefs
In Firestore, documents are sets of key-value pairs, and collections are groups of
documents. A Firestore database consists of a hierarchy of alternating collections
and documents, referred to by slash-separated paths like
"States/California/Cities/SanFrancisco".
This client is built around references to collections and documents. CollectionRefs
and DocumentRefs are lightweight values that refer to the corresponding database
entities. Creating a ref does not involve any network traffic.
states := client.Collection("States")
ny := states.Doc("NewYork")
// Or, in a single call:
ny = client.Doc("States/NewYork")
Reading
Use DocumentRef.Get to read a document. The result is a DocumentSnapshot.
Call its Data method to obtain the entire document contents as a map.
docsnap, err := ny.Get(ctx)
if err != nil {
// TODO: Handle error.
}
dataMap := docsnap.Data()
fmt.Println(dataMap)
You can also obtain a single field with DataAt, or extract the data into a struct
with DataTo. With the type definition
type State struct {
Capital string `firestore:"capital"`
Population float64 `firestore:"pop"` // in millions
}
we can extract the document's data into a value of type State:
var nyData State
if err := docsnap.DataTo(&nyData); err != nil {
// TODO: Handle error.
}
Note that this client supports struct tags beginning with "firestore:" that work like
the tags of the encoding/json package, letting you rename fields, ignore them, or
omit their values when empty.
To retrieve multiple documents from their references in a single call, use
Client.GetAll.
docsnaps, err := client.GetAll(ctx, []*firestore.DocumentRef{
states.Doc("Wisconsin"), states.Doc("Ohio"),
})
if err != nil {
// TODO: Handle error.
}
for _, ds := range docsnaps {
_ = ds // TODO: Use ds.
}
Writing
For writing individual documents, use the methods on DocumentReference.
Create creates a new document.
wr, err := ny.Create(ctx, State{
Capital: "Albany",
Population: 19.8,
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr)
The first return value is a WriteResult, which contains the time
at which the document was updated.
Create fails if the document exists. Another method, Set, either replaces an existing
document or creates a new one.
ca := states.Doc("California")
_, err = ca.Set(ctx, State{
Capital: "Sacramento",
Population: 39.14,
})
To update some fields of an existing document, use Update. It takes a list of
paths to update and their corresponding values.
_, err = ca.Update(ctx, []firestore.Update{{Path: "capital", Value: "Sacramento"}})
Use DocumentRef.Delete to delete a document.
_, err = ny.Delete(ctx)
Preconditions
You can condition Deletes or Updates on when a document was last changed. Specify
these preconditions as an option to a Delete or Update method. The check and the
write happen atomically with a single RPC.
docsnap, err = ca.Get(ctx)
if err != nil {
// TODO: Handle error.
}
_, err = ca.Update(ctx,
[]firestore.Update{{Path: "capital", Value: "Sacramento"}},
firestore.LastUpdateTime(docsnap.UpdateTime))
Here we update a doc only if it hasn't changed since we read it.
You could also do this with a transaction.
To perform multiple writes at once, use a WriteBatch. Its methods chain
for convenience.
WriteBatch.Commit sends the collected writes to the server, where they happen
atomically.
writeResults, err := client.Batch().
Create(ny, State{Capital: "Albany"}).
Update(ca, []firestore.Update{{Path: "capital", Value: "Sacramento"}}).
Delete(client.Doc("States/WestDakota")).
Commit(ctx)
Queries
You can use SQL to select documents from a collection. Begin with the collection, and
build up a query using Select, Where and other methods of Query.
q := states.Where("pop", ">", 10).OrderBy("pop", firestore.Desc)
Call the Query's Documents method to get an iterator, and use it like
the other Google Cloud Client iterators.
iter := q.Documents(ctx)
defer iter.Stop()
for {
doc, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
// TODO: Handle error.
}
fmt.Println(doc.Data())
}
To get all the documents in a collection, you can use the collection itself
as a query.
iter = client.Collection("States").Documents(ctx)
Transactions
Use a transaction to execute reads and writes atomically. All reads must happen
before any writes. Transaction creation, commit, rollback and retry are handled for
you by the Client.RunTransaction method; just provide a function and use the
read and write methods of the Transaction passed to it.
ny := client.Doc("States/NewYork")
err := client.RunTransaction(ctx, func(ctx context.Context, tx *firestore.Transaction) error {
doc, err := tx.Get(ny) // tx.Get, NOT ny.Get!
if err != nil {
return err
}
pop, err := doc.DataAt("pop")
if err != nil {
return err
}
return tx.Update(ny, []firestore.Update{{Path: "pop", Value: pop.(float64) + 0.2}})
})
if err != nil {
// TODO: Handle error.
}
*/
package firestore