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)
Supported operators include '<', '<=', '>', '>=', '==', 'in', 'array-contains', and
'array-contains-any'.
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)
Collection Group Partition Queries
¶
You can partition the documents of a Collection Group allowing for smaller subqueries.
collectionGroup = client.CollectionGroup("States")
partitions, err = collectionGroup.GetPartitionedQueries(ctx, 20)
You can also Serialize/Deserialize queries making it possible to run/stream the
queries elsewhere; another process or machine for instance.
queryProtos := make([][]byte, 0)
for _, query := range partitions {
protoBytes, err := query.Serialize()
// handle err
queryProtos = append(queryProtos, protoBytes)
...
}
for _, protoBytes := range queryProtos {
query, err := client.CollectionGroup("").Deserialize(protoBytes)
...
}
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.
}
Google Cloud Firestore Emulator
¶
This package supports the Cloud Firestore emulator, which is useful for testing and
development. Environment variables are used to indicate that Firestore traffic should be
directed to the emulator instead of the production Firestore service.
To install and run the emulator and its environment variables, see the documentation
at
https://cloud.google.com/sdk/gcloud/reference/beta/emulators/firestore/
. Once the
emulator is running, set FIRESTORE_EMULATOR_HOST to the API endpoint.
// Set FIRESTORE_EMULATOR_HOST environment variable.
err := os.Setenv("FIRESTORE_EMULATOR_HOST", "localhost:9000")
if err != nil {
// TODO: Handle error.
}
// Create client as usual.
client, err := firestore.NewClient(ctx, "my-project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
func ArrayRemove(elems ...interface{}) arrayRemove
ArrayRemove specifies elements to be removed from whatever array already
exists in the server.
If a value exists and it's an array, values are removed from it. All
duplicate values are removed.
If a value exists and it's not an array, the value is replaced by an empty
array.
If a value does not exist, an empty array is created.
ArrayRemove must be the value of a field directly; it cannot appear in
array or struct values, or in any value that is itself inside an array or
struct.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
co := client.Doc("States/Colorado")
wr, err := co.Update(ctx, []firestore.Update{
{Path: "cities", Value: firestore.ArrayRemove("Denver")},
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
func ArrayUnion(elems ...interface{}) arrayUnion
ArrayUnion specifies elements to be added to whatever array already exists in
the server, or to create an array if no value exists.
If a value exists and it's an array, values are appended to it. Any duplicate
value is ignored.
If a value exists and it's not an array, the value is replaced by an array of
the values in the ArrayUnion.
If a value does not exist, an array of the values in the ArrayUnion is created.
ArrayUnion must be the value of a field directly; it cannot appear in
array or struct values, or in any value that is itself inside an array or
struct.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
wr, err := client.Doc("States/Colorado").Create(ctx, map[string]interface{}{
"cities": firestore.ArrayUnion("Denver", "Golden", "Boulder"),
"pop": 5.5,
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
co := client.Doc("States/Colorado")
wr, err := co.Update(ctx, []firestore.Update{
{Path: "cities", Value: firestore.ArrayUnion("Broomfield")},
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
func FieldTransformIncrement(n interface{}) transform
FieldTransformIncrement returns a special value that can be used with Set, Create, or
Update that tells the server to transform the field's current value
by the given value.
The supported values are:
int, int8, int16, int32, int64
uint8, uint16, uint32
float32, float64
If the field does not yet exist, the transformation will set the field to
the given value.
func FieldTransformMaximum(n interface{}) transform
FieldTransformMaximum returns a special value that can be used with Set, Create, or
Update that tells the server to set the field to the maximum of the
field's current value and the given value.
The supported values are:
int, int8, int16, int32, int64
uint8, uint16, uint32
float32, float64
If the field is not an integer or double, or if the field does not yet
exist, the transformation will set the field to the given value. If a
maximum operation is applied where the field and the input value are of
mixed types (that is - one is an integer and one is a double) the field
takes on the type of the larger operand. If the operands are equivalent
(e.g. 3 and 3.0), the field does not change. 0, 0.0, and -0.0 are all zero.
The maximum of a zero stored value and zero input value is always the
stored value. The maximum of any numeric value x and NaN is NaN.
func FieldTransformMinimum(n interface{}) transform
FieldTransformMinimum returns a special value that can be used with Set, Create, or
Update that tells the server to set the field to the minimum of the
field's current value and the given value.
The supported values are:
int, int8, int16, int32, int64
uint8, uint16, uint32
float32, float64
If the field is not an integer or double, or if the field does not yet
exist, the transformation will set the field to the given value. If a
minimum operation is applied where the field and the input value are of
mixed types (that is - one is an integer and one is a double) the field
takes on the type of the smaller operand. If the operands are equivalent
(e.g. 3 and 3.0), the field does not change. 0, 0.0, and -0.0 are all zero.
The minimum of a zero stored value and zero input value is always the
stored value. The minimum of any numeric value x and NaN is NaN.
func Increment(n interface{}) transform
Increment is an alias for FieldTransformIncrement.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
wr, err := client.Doc("States/Colorado").Create(ctx, map[string]interface{}{
"cities": []string{"Denver", "Golden", "Boulder"},
"pop": firestore.Increment(7), // "pop" will be set to 7.
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
co := client.Doc("States/Colorado")
wr, err := co.Update(ctx, []firestore.Update{
{Path: "pop", Value: firestore.Increment(7)}, // "pop" will incremented by 7.
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
func MaxAttempts(n
int
) maxAttempts
MaxAttempts is a TransactionOption that configures the maximum number of times to
try a transaction. In defaults to DefaultTransactionMaxAttempts.
type AggregationQuery struct {
}
AggregationQuery allows for generating aggregation results of an underlying
basic query. A single AggregationQuery can contain multiple aggregations.
Get retrieves the aggregation query results from the service.
Transaction specifies that aggregation query should run within provided transaction
WithAvg specifies that the aggregation query should provide an average of the values
of the provided field in the results returned by the underlying Query.
The alias argument can be empty or a valid Firestore document field name. It can be used
as key in the AggregationResult to get the average value. If alias is empty, Firestore
will autogenerate a key.
WithAvgPath specifies that the aggregation query should provide an average of the values
of the provided field in the results returned by the underlying Query.
The path argument can be a single field or a dot-separated sequence of
fields, and must not contain any of the runes "?*/[]".
The alias argument can be empty or a valid Firestore document field name. It can be used
as key in the AggregationResult to get the average value. If alias is empty, Firestore
will autogenerate a key.
WithCount specifies that the aggregation query provide a count of results
returned by the underlying Query.
WithSum specifies that the aggregation query should provide a sum of the values
of the provided field in the results returned by the underlying Query.
The alias argument can be empty or a valid Firestore document field name. It can be used
as key in the AggregationResult to get the sum value. If alias is empty, Firestore
will autogenerate a key.
WithSumPath specifies that the aggregation query should provide a sum of the values
of the provided field in the results returned by the underlying Query.
The path argument can be a single field or a dot-separated sequence of
fields, and must not contain any of the runes "?*/[]".
The alias argument can be empty or a valid Firestore document field name. It can be used
as key in the AggregationResult to get the sum value. If alias is empty, Firestore
will autogenerate a key.
type AggregationResult map[
string
]interface{}
AggregationResult contains the results of an aggregation query.
type
AndFilter
¶
added in
v1.10.0
AndFilter represents the intersection of two or more filters.
type BulkWriter struct {
}
A BulkWriter supports concurrent writes to multiple documents. The BulkWriter
submits document writes in maximum batches of 20 writes per request. Each
request can contain many different document writes: create, delete, update,
and set are all supported.
Only one operation (create, set, update, delete) per document is allowed.
BulkWriter cannot promise atomicity: individual writes can fail or succeed
independent of each other. Bulkwriter does not apply writes in any set order;
thus a document can't have set on it immediately after creation.
Create adds a document creation write to the queue of writes to send.
Note: You cannot write to (Create, Update, Set, or Delete) the same document more than once.
Delete adds a document deletion write to the queue of writes to send.
Note: You cannot write to (Create, Update, Set, or Delete) the same document more than once.
End sends all enqueued writes in parallel and closes the BulkWriter to new requests.
After calling End(), calling any additional method automatically returns
with an error. This method completes when there are no more pending writes
in the queue.
Flush commits all writes that have been enqueued up to this point in parallel.
This method blocks execution.
Set adds a document set write to the queue of writes to send.
Note: You cannot write to (Create, Update, Set, or Delete) the same document more than once.
Update adds a document update write to the queue of writes to send.
Note: You cannot write to (Create, Update, Set, or Delete) the same document more than once.
type BulkWriterJob struct {
}
BulkWriterJob provides read-only access to the results of a BulkWriter write attempt.
Results gets the results of the BulkWriter write attempt.
This method blocks if the results for this BulkWriterJob haven't been
received.
A Client provides access to the Firestore service.
NewClient creates a new Firestore client that uses the given project.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close() // Close client when done.
_ = client // TODO: Use client.
}
Output:
NewClientWithDatabase creates a new Firestore client that accesses the
specified database.
Batch returns a WriteBatch.
Deprecated: The WriteBatch API has been replaced with the transaction and
the bulk writer API. For atomic transaction operations, use `Transaction`.
For bulk read and write operations, use `BulkWriter`.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
b := client.Batch()
_ = b // TODO: Use batch.
}
Output:
BulkWriter returns a BulkWriter instance.
The context passed to the BulkWriter remains stored through the lifecycle
of the object. This context allows callers to cancel BulkWriter operations.
Close closes any resources held by the client.
Close need not be called at program exit.
Collection creates a reference to a collection with the given path.
A path is a sequence of IDs separated by slashes.
Collection returns nil if path contains an even number of IDs or any ID is empty.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
coll1 := client.Collection("States")
coll2 := client.Collection("States/NewYork/Cities")
fmt.Println(coll1, coll2)
}
Output:
CollectionGroup creates a reference to a group of collections that include
the given ID, regardless of parent document.
For example, consider:
France/Cities/Paris = {population: 100}
Canada/Cities/Montreal = {population: 90}
CollectionGroup can be used to query across all "Cities" regardless of
its parent "Countries". See ExampleCollectionGroup for a complete example.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
// Given:
// France/Cities/Paris = {population: 100}
// Canada/Cities/Montreal = {population: 95}
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
// Query for ANY city with >95 pop, regardless of country.
docs, err := client.CollectionGroup("Cities").
Where("pop", ">", 95).
OrderBy("pop", firestore.Desc).
Limit(10).
Documents(ctx).
GetAll()
if err != nil {
// TODO: Handle error.
}
_ = docs // TODO: Use docs.
}
Output:
Collections returns an iterator over the top-level collections.
Doc creates a reference to a document with the given path.
A path is a sequence of IDs separated by slashes.
Doc returns nil if path contains an odd number of IDs or any ID is empty.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
doc1 := client.Doc("States/NewYork")
doc2 := client.Doc("States/NewYork/Cities/Albany")
fmt.Println(doc1, doc2)
}
Output:
GetAll retrieves multiple documents with a single call. The
DocumentSnapshots are returned in the order of the given DocumentRefs.
The return value will always contain the same number of DocumentSnapshots
as the number of DocumentRefs in the input.
If the same DocumentRef is specified multiple times in the input, the return
value will contain the same number of DocumentSnapshots referencing the same
document.
If a document is not present, the corresponding DocumentSnapshot's Exists
method will return false.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
docs, err := client.GetAll(ctx, []*firestore.DocumentRef{
client.Doc("States/NorthCarolina"),
client.Doc("States/SouthCarolina"),
client.Doc("States/WestCarolina"),
client.Doc("States/EastCarolina"),
})
if err != nil {
// TODO: Handle error.
}
// docs is a slice with four DocumentSnapshots, but the last two are
// nil because there is no West or East Carolina.
fmt.Println(docs)
}
Output:
RunTransaction runs f in a transaction. f should use the transaction it is given
for all Firestore operations. For any operation requiring a context, f should use
the context it is passed, not the first argument to RunTransaction.
f must not call Commit or Rollback on the provided Transaction.
If f returns nil, RunTransaction commits the transaction. If the commit fails due
to a conflicting transaction, RunTransaction retries f. It gives up and returns an
error after a number of attempts that can be configured with the MaxAttempts
option. If the commit succeeds, RunTransaction returns a nil error.
If f returns non-nil, then the transaction will be rolled back and
this method will return the same error. The function f is not retried.
Note that when f returns, the transaction is not committed. Calling code
must not assume that any of f's changes have been committed until
RunTransaction returns nil.
Since f may be called more than once, f should usually be idempotent ? that is, it
should have the same result when called multiple times.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
nm := client.Doc("States/NewMexico")
err = client.RunTransaction(ctx, func(ctx context.Context, tx *firestore.Transaction) error {
doc, err := tx.Get(nm) // tx.Get, NOT nm.Get!
if err != nil {
return err
}
pop, err := doc.DataAt("pop")
if err != nil {
return err
}
return tx.Update(nm, []firestore.Update{{Path: "pop", Value: pop.(float64) + 0.2}})
})
if err != nil {
// TODO: Handle error.
}
}
Output:
WithReadOptions specifies constraints for accessing documents from the database,
e.g. at what time snapshot to read the documents.
type CollectionGroupRef struct {
Query
}
A CollectionGroupRef is a reference to a group of collections sharing the
same ID.
GetPartitionedQueries returns a slice of Query objects, each containing a
partition of a collection group. partitionCount must be a positive value and
the number of returned partitions may be less than the requested number if
providing the desired number would result in partitions with very few documents.
If a Collection Group Query would return a large number of documents, this
can help to subdivide the query to smaller working units that can be distributed.
If the goal is to run the queries across processes or workers, it may be useful to use
`Query.Serialize` and `Query.Deserialize` to serialize the query.
type CollectionIterator struct {
}
CollectionIterator is an iterator over sub-collections of a document.
GetAll returns all the collections remaining from the iterator.
Next returns the next result. Its second return value is iterator.Done if there
are no more results. Once Next returns Done, all subsequent calls will return
Done.
PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
A CollectionRef is a reference to Firestore collection.
Add generates a DocumentRef with a unique ID. It then creates the document
with the given data, which can be a map[string]interface{}, a struct or a
pointer to a struct.
Add returns an error in the unlikely event that a document with the same ID
already exists.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
doc, wr, err := client.Collection("Users").Add(ctx, map[string]interface{}{
"name": "Alice",
"email": "aj@example.com",
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(doc, wr)
}
Output:
Doc returns a DocumentRef that refers to the document in the collection with the
given identifier.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
fl := client.Collection("States").Doc("Florida")
ta := client.Collection("States").Doc("Florida/Cities/Tampa")
fmt.Println(fl, ta)
}
Output:
DocumentRefs returns references to all the documents in the collection, including
missing documents. A missing document is a document that does not exist but has
sub-documents.
NewDoc returns a DocumentRef with a uniquely generated ID.
NewDoc will panic if crypto/rand cannot generate enough bytes to make a new
doc ID.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
doc := client.Collection("Users").NewDoc()
fmt.Println(doc)
}
Output:
WithReadOptions specifies constraints for accessing documents from the database,
e.g. at what time snapshot to read the documents.
CompositeFilter represents a composite Firestore filter.
Direction is the sort direction for result ordering.
A DocumentChange describes the change to a document from one query snapshot to the next.
type DocumentChangeKind
int
DocumentChangeKind describes the kind of change to a document between
query snapshots.
type DocumentIterator struct {
}
DocumentIterator is an iterator over documents returned by a query.
GetAll returns all the documents remaining from the iterator.
It is not necessary to call Stop on the iterator after calling GetAll.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
q := client.Collection("States").
Where("pop", ">", 10).
OrderBy("pop", firestore.Desc).
Limit(10) // a good idea with GetAll, to avoid filling memory
docs, err := q.Documents(ctx).GetAll()
if err != nil {
// TODO: Handle error.
}
for _, doc := range docs {
fmt.Println(doc.Data())
}
}
Output:
Next returns the next result. Its second return value is iterator.Done if there
are no more results. Once Next returns Done, all subsequent calls will return
Done.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
"google.golang.org/api/iterator"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
q := client.Collection("States").
Where("pop", ">", 10).
OrderBy("pop", firestore.Desc)
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())
}
}
Output:
Stop stops the iterator, freeing its resources.
Always call Stop when you are done with a DocumentIterator.
It is not safe to call Stop concurrently with Next.
A DocumentRef is a reference to a Firestore document.
Collection returns a reference to sub-collection of this document.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
mi := client.Collection("States").Doc("Michigan")
cities := mi.Collection("Cities")
fmt.Println(cities)
}
Output:
Collections returns an iterator over the immediate sub-collections of the document.
Create creates the document with the given data.
It returns an error if a document with the same ID already exists.
The data argument can be a map with string keys, a struct, or a pointer to a
struct. The map keys or exported struct fields become the fields of the firestore
document.
The values of data are converted to Firestore values as follows:
- bool converts to Bool.
- string converts to String.
- int, int8, int16, int32 and int64 convert to Integer.
- uint8, uint16 and uint32 convert to Integer. uint, uint64 and uintptr are disallowed,
because they may be able to represent values that cannot be represented in an int64,
which is the underlying type of a Integer.
- float32 and float64 convert to Double.
- []byte converts to Bytes.
- time.Time and *ts.Timestamp convert to Timestamp. ts is the package
"github.com/golang/protobuf/ptypes/timestamp".
- *latlng.LatLng converts to GeoPoint. latlng is the package
"google.golang.org/genproto/googleapis/type/latlng". You should always use
a pointer to a LatLng.
- Slices convert to Array.
- *firestore.DocumentRef converts to Reference.
- Maps and structs convert to Map.
- nils of any type convert to Null.
Pointers and interface{} are also permitted, and their elements processed
recursively.
Struct fields can have tags like those used by the encoding/json package. Tags
begin with "firestore:" and are followed by "-", meaning "ignore this field," or
an alternative name for the field. Following the name, these comma-separated
options may be provided:
- omitempty: Do not encode this field if it is empty. A value is empty
if it is a zero value, or an array, slice or map of length zero.
- serverTimestamp: The field must be of type time.Time. serverTimestamp
is a sentinel token that tells Firestore to substitute the server time
into that field. When writing, if the field has the zero value, the
server will populate the stored document with the time that the request
is processed. However, if the field value is non-zero it won't be saved.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
wr, err := client.Doc("States/Colorado").Create(ctx, map[string]interface{}{
"capital": "Denver",
"pop": 5.5,
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
type State struct {
Capital string `firestore:"capital"`
Population float64 `firestore:"pop"` // in millions
}
wr, err := client.Doc("States/Colorado").Create(ctx, State{
Capital: "Denver",
Population: 5.5,
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
Delete deletes the document. If the document doesn't exist, it does nothing
and returns no error.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
// Oops, Ontario is a Canadian province...
if _, err = client.Doc("States/Ontario").Delete(ctx); err != nil {
// TODO: Handle error.
}
}
Output:
Get retrieves the document. If the document does not exist, Get return a NotFound error, which
can be checked with
status.Code(err) == codes.NotFound
In that case, Get returns a non-nil DocumentSnapshot whose Exists method return false and whose
ReadTime is the time of the failed read operation.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
docsnap, err := client.Doc("States/Ohio").Get(ctx)
if err != nil {
// TODO: Handle error.
}
_ = docsnap // TODO: Use DocumentSnapshot.
}
Output:
Set creates or overwrites the document with the given data. See DocumentRef.Create
for the acceptable values of data. Without options, Set overwrites the document
completely. Specify one of the Merge options to preserve an existing document's
fields. To delete some fields, use a Merge option with firestore.Delete as the
field value.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
// Overwrite the document with the given data. Any other fields currently
// in the document will be removed.
wr, err := client.Doc("States/Alabama").Set(ctx, map[string]interface{}{
"capital": "Montgomery",
"pop": 4.9,
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
// Overwrite only the fields in the map; preserve all others.
_, err = client.Doc("States/Alabama").Set(ctx, map[string]interface{}{
"pop": 5.2,
}, firestore.MergeAll)
if err != nil {
// TODO: Handle error.
}
type State struct {
Capital string `firestore:"capital"`
Population float64 `firestore:"pop"` // in millions
}
// To do a merging Set with struct data, specify the exact fields to overwrite.
// MergeAll is disallowed here, because it would probably be a mistake: the "capital"
// field would be overwritten with the empty string.
_, err = client.Doc("States/Alabama").Set(ctx, State{Population: 5.2}, firestore.Merge([]string{"pop"}))
if err != nil {
// TODO: Handle error.
}
}
Output:
Snapshots returns an iterator over snapshots of the document. Each time the document
changes or is added or deleted, a new snapshot will be generated.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
iter := client.Doc("States/Idaho").Snapshots(ctx)
defer iter.Stop()
for {
docsnap, err := iter.Next()
if err != nil {
// TODO: Handle error.
}
_ = docsnap // TODO: Use DocumentSnapshot.
}
}
Output:
Update updates the document. The values at the given
field paths are replaced, but other fields of the stored document are untouched.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
tenn := client.Doc("States/Tennessee")
wr, err := tenn.Update(ctx, []firestore.Update{
{Path: "pop", Value: 6.6},
{FieldPath: []string{".", "*", "/"}, Value: "odd"},
})
if err != nil {
// TODO: Handle error.
}
fmt.Println(wr.UpdateTime)
}
Output:
WithReadOptions specifies constraints for accessing documents from the database,
e.g. at what time snapshot to read the documents.
type DocumentRefIterator struct {
}
DocumentRefIterator is an iterator over DocumentRefs.
GetAll returns all the DocumentRefs remaining from the iterator.
Next returns the next result. Its second return value is iterator.Done if there
are no more results. Once Next returns Done, all subsequent calls will return
Done.
PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
A DocumentSnapshot contains document data and metadata.
Data returns the DocumentSnapshot's fields as a map.
It is equivalent to
var m map[string]interface{}
d.DataTo(&m)
except that it returns nil if the document does not exist.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
docsnap, err := client.Doc("States/Ohio").Get(ctx)
if err != nil {
// TODO: Handle error.
}
ohioMap := docsnap.Data()
fmt.Println(ohioMap["capital"])
}
Output:
DataAt returns the data value denoted by path.
The path argument can be a single field or a dot-separated sequence of
fields, and must not contain any of the runes "?*/[]". Use DataAtPath instead for
such a path.
See DocumentSnapshot.DataTo for how Firestore values are converted to Go values.
If the document does not exist, DataAt returns a NotFound error.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
docsnap, err := client.Doc("States/Ohio").Get(ctx)
if err != nil {
// TODO: Handle error.
}
cap, err := docsnap.DataAt("capital")
if err != nil {
// TODO: Handle error.
}
fmt.Println(cap)
}
Output:
DataAtPath returns the data value denoted by the FieldPath fp.
If the document does not exist, DataAtPath returns a NotFound error.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
docsnap, err := client.Doc("States/Ohio").Get(ctx)
if err != nil {
// TODO: Handle error.
}
pop, err := docsnap.DataAtPath([]string{"capital", "population"})
if err != nil {
// TODO: Handle error.
}
fmt.Println(pop)
}
Output:
DataTo uses the document's fields to populate p, which can be a pointer to a
map[string]interface{} or a pointer to a struct.
Firestore field values are converted to Go values as follows:
- Null converts to nil.
- Bool converts to bool.
- String converts to string.
- Integer converts int64. When setting a struct field, any signed or unsigned
integer type is permitted except uint, uint64 or uintptr. Overflow is detected
and results in an error.
- Double converts to float64. When setting a struct field, float32 is permitted.
Overflow is detected and results in an error.
- Bytes is converted to []byte.
- Timestamp converts to time.Time.
- GeoPoint converts to *latlng.LatLng, where latlng is the package
"google.golang.org/genproto/googleapis/type/latlng".
- Arrays convert to []interface{}. When setting a struct field, the field
may be a slice or array of any type and is populated recursively.
Slices are resized to the incoming value's size, while arrays that are too
long have excess elements filled with zero values. If the array is too short,
excess incoming values will be dropped.
- Maps convert to map[string]interface{}. When setting a struct field,
maps of key type string and any value type are permitted, and are populated
recursively.
- References are converted to *firestore.DocumentRefs.
Field names given by struct field tags are observed, as described in
DocumentRef.Create.
Only the fields actually present in the document are used to populate p. Other fields
of p are left unchanged.
If the document does not exist, DataTo returns a NotFound error.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
docsnap, err := client.Doc("States/Ohio").Get(ctx)
if err != nil {
// TODO: Handle error.
}
type State struct {
Capital string `firestore:"capital"`
Population float64 `firestore:"pop"` // in millions
}
var s State
if err := docsnap.DataTo(&s); err != nil {
// TODO: Handle error.
}
fmt.Println(s)
}
Output:
Exists reports whether the DocumentSnapshot represents an existing document.
Even if Exists returns false, the Ref and ReadTime fields of the DocumentSnapshot
are valid.
type DocumentSnapshotIterator struct {
}
DocumentSnapshotIterator is an iterator over snapshots of a document.
Call Next on the iterator to get a snapshot of the document each time it changes.
Call Stop on the iterator when done.
For an example, see DocumentRef.Snapshots.
Next blocks until the document changes, then returns the DocumentSnapshot for
the current state of the document. If the document has been deleted, Next
returns a DocumentSnapshot whose Exists method returns false.
Next is not expected to return iterator.Done unless it is called after Stop.
Rarely, networking issues may also cause iterator.Done to be returned.
Stop stops receiving snapshots. You should always call Stop when you are done with
a DocumentSnapshotIterator, to free up resources. It is not safe to call Stop
concurrently with Next.
type EntityFilter interface {
}
EntityFilter represents a Firestore filter.
A FieldPath is a non-empty sequence of non-empty fields that reference a value.
A FieldPath value should only be necessary if one of the field names contains
one of the runes ".?*/[]". Most methods accept a simpler form of field path
as a string in which the individual fields are separated by dots.
For example,
[]string{"a", "b"}
is equivalent to the string form
"a.b"
but
[]string{"*"}
has no equivalent string form.
OrFilter represents a union of two or more filters.
type Precondition interface {
}
A Precondition modifies a Firestore update or delete operation.
Exists is a Precondition that checks for the existence of a resource before
writing to it. If the check fails, the write does not occur.
LastUpdateTime returns a Precondition that checks that a resource must exist and
must have last been updated at the given time. If the check fails, the write
does not occur.
type PropertyFilter struct {
Path
string
Operator
string
Value interface{}
}
PropertyFilter represents a filter on single property.
Path can be a single field or a dot-separated sequence of fields
denoting property path, and must not contain any of the runes "?*/[]".
Operator must be one of "==", "!=", "<", "<=", ">", ">=",
"array-contains", "array-contains-any", "in" or "not-in".
type PropertyPathFilter struct {
Path
FieldPath
Operator
string
Value interface{}
}
PropertyPathFilter represents a filter on single property.
Path can be an array of fields denoting property path.
Operator must be one of "==", "!=", "<", "<=", ">", ">=",
"array-contains", "array-contains-any", "in" or "not-in".
Query represents a Firestore query.
Query values are immutable. Each Query method creates
a new Query; it does not modify the old.
Deserialize takes a slice of bytes holding the wire-format message of RunQueryRequest,
the underlying proto message used by Queries. It then populates and returns a
Query object that can be used to execut that Query.
Documents returns an iterator over the query's resulting documents.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
q := client.Collection("States").Select("pop").
Where("pop", ">", 10).
OrderBy("pop", firestore.Desc).
Limit(10)
iter1 := q.Documents(ctx)
_ = iter1 // TODO: Use iter1.
// You can call Documents directly on a CollectionRef as well.
iter2 := client.Collection("States").Documents(ctx)
_ = iter2 // TODO: Use iter2.
}
Output:
This example is just like the one above, but illustrates
how to use the XXXPath methods of Query for field paths
that can't be expressed as a dot-separated string.
package main
import (
"context"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
q := client.Collection("Unusual").SelectPaths([]string{"*"}, []string{"[~]"}).
WherePath([]string{"/"}, ">", 10).
OrderByPath([]string{"/"}, firestore.Desc).
Limit(10)
iter1 := q.Documents(ctx)
_ = iter1 // TODO: Use iter1.
// You can call Documents directly on a CollectionRef as well.
iter2 := client.Collection("States").Documents(ctx)
_ = iter2 // TODO: Use iter2.
}
Output:
func (q
Query
) EndAt(docSnapshotOrFieldValues ...interface{})
Query
EndAt returns a new Query that specifies that results should end at the
document with the given field values. See Query.StartAt for more information.
Calling EndAt overrides a previous call to EndAt or EndBefore.
func (q
Query
) EndBefore(docSnapshotOrFieldValues ...interface{})
Query
EndBefore returns a new Query that specifies that results should end just before
the document with the given field values. See Query.StartAt for more information.
Calling EndBefore overrides a previous call to EndAt or EndBefore.
Limit returns a new Query that specifies the maximum number of first results
to return. It must not be negative.
LimitToLast returns a new Query that specifies the maximum number of last
results to return. It must not be negative.
NewAggregationQuery returns an AggregationQuery with this query as its
base query.
Offset returns a new Query that specifies the number of initial results to skip.
It must not be negative.
OrderBy returns a new Query that specifies the order in which results are
returned. A Query can have multiple OrderBy/OrderByPath specifications.
OrderBy appends the specification to the list of existing ones.
The path argument can be a single field or a dot-separated sequence of
fields, and must not contain any of the runes "?*/[]".
To order by document name, use the special field path DocumentID.
OrderByPath returns a new Query that specifies the order in which results are
returned. A Query can have multiple OrderBy/OrderByPath specifications.
OrderByPath appends the specification to the list of existing ones.
Select returns a new Query that specifies the paths
to return from the result documents.
Each path argument can be a single field or a dot-separated sequence of
fields, and must not contain any of the runes "?*/[]".
An empty Select call will produce a query that returns only document IDs.
SelectPaths returns a new Query that specifies the field paths
to return from the result documents.
An empty SelectPaths call will produce a query that returns only document IDs.
Serialize creates a RunQueryRequest wire-format byte slice from a Query object.
This can be used in combination with Deserialize to marshal Query objects.
This could be useful, for instance, if executing a query formed in one
process in another.
Snapshots returns an iterator over snapshots of the query. Each time the query
results change, a new snapshot will be generated.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
"google.golang.org/api/iterator"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
q := client.Collection("States").
Where("pop", ">", 10).
OrderBy("pop", firestore.Desc).
Limit(10)
qsnapIter := q.Snapshots(ctx)
// Listen forever for changes to the query's results.
for {
qsnap, err := qsnapIter.Next()
if err == iterator.Done {
break
}
if err != nil {
// TODO: Handle error.
}
fmt.Printf("At %s there were %d results.\n", qsnap.ReadTime, qsnap.Size)
_ = qsnap.Documents // TODO: Iterate over the results if desired.
_ = qsnap.Changes // TODO: Use the list of incremental changes if desired.
}
}
Output:
func (q
Query
) StartAfter(docSnapshotOrFieldValues ...interface{})
Query
StartAfter returns a new Query that specifies that results should start just after
the document with the given field values. See Query.StartAt for more information.
Calling StartAfter overrides a previous call to StartAt or StartAfter.
func (q
Query
) StartAt(docSnapshotOrFieldValues ...interface{})
Query
StartAt returns a new Query that specifies that results should start at
the document with the given field values.
StartAt may be called with a single DocumentSnapshot, representing an
existing document within the query. The document must be a direct child of
the location being queried (not a parent document, or document in a
different collection, or a grandchild document, for example).
Otherwise, StartAt should be called with one field value for each OrderBy clause,
in the order that they appear. For example, in
q.OrderBy("X", Asc).OrderBy("Y", Desc).StartAt(1, 2)
results will begin at the first document where X = 1 and Y = 2.
If an OrderBy call uses the special DocumentID field path, the corresponding value
should be the document ID relative to the query's collection. For example, to
start at the document "NewYork" in the "States" collection, write
client.Collection("States").OrderBy(DocumentID, firestore.Asc).StartAt("NewYork")
Calling StartAt overrides a previous call to StartAt or StartAfter.
Where returns a new Query that filters the set of results.
A Query can have multiple filters.
The path argument can be a single field or a dot-separated sequence of
fields, and must not contain any of the runes "?*/[]".
The op argument must be one of "==", "!=", "<", "<=", ">", ">=",
"array-contains", "array-contains-any", "in" or "not-in".
WARNING: Using WhereEntity with Simple and Composite filters is recommended.
WhereEntity returns a query with provided filter.
EntityFilter can be a simple filter or a composite filter
PropertyFilter and PropertyPathFilter are supported simple filters
AndFilter and OrFilter are supported composite filters
Entity filters in multiple calls are joined together by AND
WherePath returns a new Query that filters the set of results.
A Query can have multiple filters.
The op argument must be one of "==", "!=", "<", "<=", ">", ">=",
"array-contains", "array-contains-any", "in" or "not-in".
WARNING: Using WhereEntity with Simple and Composite filters is recommended.
WithReadOptions specifies constraints for accessing documents from the database,
e.g. at what time snapshot to read the documents.
A QuerySnapshot is a snapshot of query results. It is returned by
QuerySnapshotIterator.Next whenever the results of a query change.
type QuerySnapshotIterator struct {
Query
Query
}
QuerySnapshotIterator is an iterator over snapshots of a query.
Call Next on the iterator to get a snapshot of the query's results each time they change.
Call Stop on the iterator when done.
For an example, see Query.Snapshots.
Next blocks until the query's results change, then returns a QuerySnapshot for
the current results.
Next is not expected to return iterator.Done unless it is called after Stop.
Rarely, networking issues may also cause iterator.Done to be returned.
Stop stops receiving snapshots. You should always call Stop when you are done with
a QuerySnapshotIterator, to free up resources. It is not safe to call Stop
concurrently with Next.
type Queryer interface {
}
A Queryer is a Query or a CollectionRef. CollectionRefs act as queries whose
results are all the documents in the collection.
type ReadOption interface {
}
ReadOption interface allows for abstraction of computing read time settings.
ReadTime specifies a time-specific snapshot of the database to read.
type SetOption interface {
}
A SetOption modifies a Firestore set operation.
MergeAll is a SetOption that causes all the field paths given in the data argument
to Set to be overwritten. It is not supported for struct data.
Merge returns a SetOption that causes only the given field paths to be
overwritten. Other fields on the existing document will be untouched. It is an
error if a provided field path does not refer to a value in the data passed to
Set.
SimpleFilter represents a simple Firestore filter.
type Transaction struct {
}
Transaction represents a Firestore transaction.
Create adds a Create operation to the Transaction.
See DocumentRef.Create for details.
Delete adds a Delete operation to the Transaction.
See DocumentRef.Delete for details.
DocumentRefs returns references to all the documents in the collection, including
missing documents. A missing document is a document that does not exist but has
sub-documents.
Documents returns a DocumentIterator based on given Query or CollectionRef. The
results will be in the context of the transaction.
Get gets the document in the context of the transaction. The transaction holds a
pessimistic lock on the returned document. If the document does not exist, Get
returns a NotFound error, which can be checked with
status.Code(err) == codes.NotFound
GetAll retrieves multiple documents with a single call. The DocumentSnapshots are
returned in the order of the given DocumentRefs. If a document is not present, the
corresponding DocumentSnapshot's Exists method will return false. The transaction
holds a pessimistic lock on all of the returned documents.
Set adds a Set operation to the Transaction.
See DocumentRef.Set for details.
Update adds a new Update operation to the Transaction.
See DocumentRef.Update for details.
WithReadOptions specifies constraints for accessing documents from the database,
e.g. at what time snapshot to read the documents.
type TransactionOption interface {
}
A TransactionOption is an option passed to Client.Transaction.
An Update describes an update to a value referred to by a path.
An Update should have either a non-empty Path or a non-empty FieldPath,
but not both.
See DocumentRef.Create for acceptable values.
To delete a field, specify firestore.Delete as the value.
type WriteBatch struct {
}
A WriteBatch holds multiple database updates. Build a batch with the Create, Set,
Update and Delete methods, then run it with the Commit method. Errors in Create,
Set, Update or Delete are recorded instead of being returned immediately. The
first such error is returned by Commit.
Deprecated: The WriteBatch API has been replaced with the transaction and
the bulk writer API. For atomic transaction operations, use `Transaction`.
For bulk read and write operations, use `BulkWriter`.
Commit applies all the writes in the batch to the database atomically. Commit
returns an error if there are no writes in the batch, if any errors occurred in
constructing the writes, or if the Commmit operation fails.
package main
import (
"context"
"fmt"
"cloud.google.com/go/firestore"
)
func main() {
ctx := context.Background()
client, err := firestore.NewClient(ctx, "project-id")
if err != nil {
// TODO: Handle error.
}
defer client.Close()
type State struct {
Capital string `firestore:"capital"`
Population float64 `firestore:"pop"` // in millions
}
ny := client.Doc("States/NewYork")
ca := client.Doc("States/California")
writeResults, err := client.Batch().
Create(ny, State{Capital: "Albany", Population: 19.8}).
Set(ca, State{Capital: "Sacramento", Population: 39.14}).
Delete(client.Doc("States/WestDakota")).
Commit(ctx)
if err != nil {
// TODO: Handle error.
}
fmt.Println(writeResults)
}
Output:
Create adds a Create operation to the batch.
See DocumentRef.Create for details.
Delete adds a Delete operation to the batch.
See DocumentRef.Delete for details.
Set adds a Set operation to the batch.
See DocumentRef.Set for details.
Update adds an Update operation to the batch.
See DocumentRef.Update for details.
type WriteResult struct {
UpdateTime
time
.
Time
}
A WriteResult is returned by methods that write documents.