-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
collref.go
153 lines (134 loc) · 4.49 KB
/
collref.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
// 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
// readSettings specifies constraints for reading documents in the collection
// e.g. read time
readSettings *readSettings
}
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",
},
readSettings: &readSettings{},
}
}
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,
},
readSettings: &readSettings{},
}
}
// 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, c.readSettings)
}
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)
}
// WithReadOptions specifies constraints for accessing documents from the database,
// e.g. at what time snapshot to read the documents.
func (c *CollectionRef) WithReadOptions(opts ...ReadOption) *CollectionRef {
for _, ro := range opts {
ro.apply(c.readSettings)
}
return c
}