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
|
// Copyright 2017 Google LLC
//
// 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.
package firestore
import (
"context"
"crypto/rand"
"fmt"
)
// A CollectionRef is a reference to Firestore collection.
type CollectionRef struct {
c *Client
// The full resource path of the collection's parent. Typically Parent.Path,
// or c.path if Parent is nil. May be different if this CollectionRef was
// created from a stored reference to a different project/DB. Always
// includes /documents - that is, the parent is minimally considered to be
// "<db>/documents".
//
// For example, "projects/P/databases/D/documents/coll-1/doc-1".
parentPath string
// The shorter resource path of the collection. A collection "coll-2" in
// document "doc-1" in collection "coll-1" would be: "coll-1/doc-1/coll-2".
selfPath string
// Parent is the document of which this collection is a part. It is
// nil for top-level collections.
Parent *DocumentRef
// The full resource path of the collection: "projects/P/databases/D/documents..."
Path string
// ID is the collection identifier.
ID string
// Use the methods of Query on a CollectionRef to create and run queries.
Query
}
func newTopLevelCollRef(c *Client, dbPath, id string) *CollectionRef {
return &CollectionRef{
c: c,
ID: id,
parentPath: dbPath + "/documents",
selfPath: id,
Path: dbPath + "/documents/" + id,
Query: Query{
c: c,
collectionID: id,
path: dbPath + "/documents/" + id,
parentPath: dbPath + "/documents",
},
}
}
func newCollRefWithParent(c *Client, parent *DocumentRef, id string) *CollectionRef {
selfPath := parent.shortPath + "/" + id
return &CollectionRef{
c: c,
Parent: parent,
ID: id,
parentPath: parent.Path,
selfPath: selfPath,
Path: parent.Path + "/" + id,
Query: Query{
c: c,
collectionID: id,
path: parent.Path + "/" + id,
parentPath: parent.Path,
},
}
}
// Doc returns a DocumentRef that refers to the document in the collection with the
// given identifier.
func (c *CollectionRef) Doc(id string) *DocumentRef {
if c == nil {
return nil
}
return newDocRef(c, id)
}
// 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.
func (c *CollectionRef) NewDoc() *DocumentRef {
return c.Doc(uniqueID())
}
// 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.
func (c *CollectionRef) Add(ctx context.Context, data interface{}) (*DocumentRef, *WriteResult, error) {
d := c.NewDoc()
wr, err := d.Create(ctx, data)
if err != nil {
return nil, nil, err
}
return d, wr, nil
}
// 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.
func (c *CollectionRef) DocumentRefs(ctx context.Context) *DocumentRefIterator {
return newDocumentRefIterator(ctx, c, nil)
}
const alphanum = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
func uniqueID() string {
b := make([]byte, 20)
if _, err := rand.Read(b); err != nil {
panic(fmt.Sprintf("firestore: crypto/rand.Read error: %v", err))
}
for i, byt := range b {
b[i] = alphanum[int(byt)%len(alphanum)]
}
return string(b)
}
|