google-cloud-firestore 2.4.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AUTHENTICATION.md +2 -1
- data/CHANGELOG.md +35 -0
- data/CONTRIBUTING.md +4 -5
- data/LOGGING.md +1 -1
- data/lib/google/cloud/firestore/batch.rb +3 -4
- data/lib/google/cloud/firestore/client.rb +17 -23
- data/lib/google/cloud/firestore/collection_group.rb +136 -0
- data/lib/google/cloud/firestore/collection_reference.rb +9 -6
- data/lib/google/cloud/firestore/collection_reference_list.rb +3 -3
- data/lib/google/cloud/firestore/convert.rb +151 -173
- data/lib/google/cloud/firestore/document_reference.rb +9 -2
- data/lib/google/cloud/firestore/document_reference/list.rb +5 -6
- data/lib/google/cloud/firestore/field_path.rb +2 -2
- data/lib/google/cloud/firestore/field_value.rb +7 -2
- data/lib/google/cloud/firestore/query.rb +88 -19
- data/lib/google/cloud/firestore/query_partition.rb +80 -0
- data/lib/google/cloud/firestore/resource_path.rb +58 -0
- data/lib/google/cloud/firestore/service.rb +18 -1
- data/lib/google/cloud/firestore/transaction.rb +5 -5
- data/lib/google/cloud/firestore/version.rb +1 -1
- data/lib/google/cloud/firestore/watch/inventory.rb +9 -8
- data/lib/google/cloud/firestore/watch/listener.rb +3 -4
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91324b3d891244579ee53512847340a286c4cf1727c9a4eb5086966355029c93
|
4
|
+
data.tar.gz: ad3b9d4907e71877a82d72a3d3f7c55952c45e0ea53ecb8becd8bc7569ef4bb9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2f11c5888b49916f5383f1a7b46c190e35897e79d376e48f6ef950246fd91179b9f33a05aec1fb932ff72fe262174fca1b5ed4c8d4f8a4e1f3f69b5302bdbaf
|
7
|
+
data.tar.gz: 24bd04f73584eeac0840fc0619c4003284c6193202763e751dd1bbf4c02539f4a44486587953cf90c5bd133377d02d8c871669affeaa9a22e2fa863c6f718f17
|
data/AUTHENTICATION.md
CHANGED
@@ -95,7 +95,8 @@ client = Google::Cloud::Firestore.new
|
|
95
95
|
|
96
96
|
### Configuration
|
97
97
|
|
98
|
-
The **Project ID** and **Credentials JSON** can be configured
|
98
|
+
The **Project ID** and the path to the **Credentials JSON** file can be configured
|
99
|
+
instead of placing them in environment variables or providing them as arguments.
|
99
100
|
|
100
101
|
```ruby
|
101
102
|
require "google/cloud/firestore"
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,40 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 2.6.1 / 2021-07-08
|
4
|
+
|
5
|
+
#### Documentation
|
6
|
+
|
7
|
+
* Update AUTHENTICATION.md in handwritten packages
|
8
|
+
|
9
|
+
### 2.6.0 / 2021-06-15
|
10
|
+
|
11
|
+
#### Features
|
12
|
+
|
13
|
+
* Add support for Query Partitions
|
14
|
+
* Add CollectionGroup
|
15
|
+
* Update Client#col_group to return CollectionGroup (subclass of Query)
|
16
|
+
* Add QueryPartition
|
17
|
+
* Add QueryPartition::List
|
18
|
+
* Add Query#to_json and Query.from_json
|
19
|
+
|
20
|
+
### 2.5.1 / 2021-04-19
|
21
|
+
|
22
|
+
#### Bug Fixes
|
23
|
+
|
24
|
+
* Add GRPC::Unknown to retryable errors in Watch::Listener
|
25
|
+
|
26
|
+
### 2.5.0 / 2021-03-10
|
27
|
+
|
28
|
+
#### Features
|
29
|
+
|
30
|
+
* Drop support for Ruby 2.4 and add support for Ruby 3.0
|
31
|
+
|
32
|
+
### 2.4.1 / 2021-01-06
|
33
|
+
|
34
|
+
#### Bug Fixes
|
35
|
+
|
36
|
+
* Replace usage of Write.transform with Write.update_transforms
|
37
|
+
|
3
38
|
### 2.4.0 / 2020-11-19
|
4
39
|
|
5
40
|
#### Features
|
data/CONTRIBUTING.md
CHANGED
@@ -24,7 +24,7 @@ be able to accept your pull requests.
|
|
24
24
|
In order to use the google-cloud-firestore console and run the project's tests,
|
25
25
|
there is a small amount of setup:
|
26
26
|
|
27
|
-
1. Install Ruby. google-cloud-firestore requires Ruby 2.
|
27
|
+
1. Install Ruby. google-cloud-firestore requires Ruby 2.5+. You may choose to
|
28
28
|
manage your Ruby and gem installations with [RVM](https://rvm.io/),
|
29
29
|
[rbenv](https://github.com/rbenv/rbenv), or
|
30
30
|
[chruby](https://github.com/postmodern/chruby).
|
@@ -45,7 +45,7 @@ there is a small amount of setup:
|
|
45
45
|
|
46
46
|
```sh
|
47
47
|
$ cd google-cloud-firestore/
|
48
|
-
$ bundle
|
48
|
+
$ bundle install
|
49
49
|
```
|
50
50
|
|
51
51
|
## Console
|
@@ -119,15 +119,14 @@ If you alter an example's title, you may encounter breaking tests.
|
|
119
119
|
### Firestore Acceptance Tests
|
120
120
|
|
121
121
|
The Firestore acceptance tests interact with the live service API. Follow the
|
122
|
-
instructions in the {file:AUTHENTICATION.md Authentication
|
122
|
+
instructions in the {file:AUTHENTICATION.md Authentication Guide} for enabling
|
123
123
|
the Firestore API. Occasionally, some API features may not yet be generally
|
124
124
|
available, making it difficult for some contributors to successfully run the
|
125
125
|
entire acceptance test suite. However, please ensure that you do successfully
|
126
126
|
run acceptance tests for any code areas covered by your pull request.
|
127
127
|
|
128
128
|
To run the acceptance tests, first create and configure a project in the Google
|
129
|
-
Developers Console, as described in the {file:AUTHENTICATION.md Authentication
|
130
|
-
guide}. Be sure to download the JSON KEY file. Make note of the PROJECT_ID and
|
129
|
+
Developers Console, as described in the {file:AUTHENTICATION.md Authentication Guide}. Be sure to download the JSON KEY file. Make note of the PROJECT_ID and
|
131
130
|
the KEYFILE location on your system.
|
132
131
|
|
133
132
|
Before you can run the Firestore acceptance tests, you must first create indexes
|
data/LOGGING.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
To enable logging for this library, set the logger for the underlying
|
4
4
|
[gRPC](https://github.com/grpc/grpc/tree/master/src/ruby) library. The logger
|
5
5
|
that you set may be a Ruby stdlib
|
6
|
-
[`Logger`](https://ruby-doc.org/stdlib
|
6
|
+
[`Logger`](https://ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger.html) as
|
7
7
|
shown below, or a
|
8
8
|
[`Google::Cloud::Logging::Logger`](https://googleapis.dev/ruby/google-cloud-logging/latest)
|
9
9
|
that will write logs to [Stackdriver
|
@@ -119,7 +119,7 @@ module Google
|
|
119
119
|
|
120
120
|
doc_path = coalesce_doc_path_argument doc
|
121
121
|
|
122
|
-
@writes << Convert.
|
122
|
+
@writes << Convert.write_for_create(doc_path, data)
|
123
123
|
|
124
124
|
nil
|
125
125
|
end
|
@@ -218,7 +218,7 @@ module Google
|
|
218
218
|
|
219
219
|
doc_path = coalesce_doc_path_argument doc
|
220
220
|
|
221
|
-
@writes << Convert.
|
221
|
+
@writes << Convert.write_for_set(doc_path, data, merge: merge)
|
222
222
|
|
223
223
|
nil
|
224
224
|
end
|
@@ -322,8 +322,7 @@ module Google
|
|
322
322
|
|
323
323
|
doc_path = coalesce_doc_path_argument doc
|
324
324
|
|
325
|
-
@writes << Convert.
|
326
|
-
update_time: update_time)
|
325
|
+
@writes << Convert.write_for_update(doc_path, data, update_time: update_time)
|
327
326
|
|
328
327
|
nil
|
329
328
|
end
|
@@ -20,6 +20,7 @@ require "google/cloud/firestore/field_value"
|
|
20
20
|
require "google/cloud/firestore/collection_reference"
|
21
21
|
require "google/cloud/firestore/document_reference"
|
22
22
|
require "google/cloud/firestore/document_snapshot"
|
23
|
+
require "google/cloud/firestore/collection_group"
|
23
24
|
require "google/cloud/firestore/batch"
|
24
25
|
require "google/cloud/firestore/transaction"
|
25
26
|
|
@@ -100,11 +101,11 @@ module Google
|
|
100
101
|
# puts col.collection_id
|
101
102
|
# end
|
102
103
|
#
|
103
|
-
def cols
|
104
|
+
def cols &block
|
104
105
|
ensure_service!
|
105
106
|
grpc = service.list_collections "#{path}/documents"
|
106
107
|
cols_enum = CollectionReferenceList.from_grpc(grpc, self, "#{path}/documents").all
|
107
|
-
cols_enum.each
|
108
|
+
cols_enum.each(&block) if block_given?
|
108
109
|
cols_enum
|
109
110
|
end
|
110
111
|
alias collections cols
|
@@ -139,7 +140,7 @@ module Google
|
|
139
140
|
alias collection col
|
140
141
|
|
141
142
|
##
|
142
|
-
# Creates and returns a new
|
143
|
+
# Creates and returns a new collection group that includes all documents in the
|
143
144
|
# database that are contained in a collection or subcollection with the
|
144
145
|
# given collection_id.
|
145
146
|
#
|
@@ -147,7 +148,7 @@ module Google
|
|
147
148
|
# over. Every collection or subcollection with this ID as the last
|
148
149
|
# segment of its path will be included. Cannot contain a slash (`/`).
|
149
150
|
#
|
150
|
-
# @return [
|
151
|
+
# @return [CollectionGroup] The created collection group.
|
151
152
|
#
|
152
153
|
# @example
|
153
154
|
# require "google/cloud/firestore"
|
@@ -155,9 +156,9 @@ module Google
|
|
155
156
|
# firestore = Google::Cloud::Firestore.new
|
156
157
|
#
|
157
158
|
# # Get the cities collection group query
|
158
|
-
#
|
159
|
+
# col_group = firestore.col_group "cities"
|
159
160
|
#
|
160
|
-
#
|
161
|
+
# col_group.get do |city|
|
161
162
|
# puts "#{city.document_id} has #{city[:population]} residents."
|
162
163
|
# end
|
163
164
|
#
|
@@ -166,15 +167,8 @@ module Google
|
|
166
167
|
raise ArgumentError, "Invalid collection_id: '#{collection_id}', " \
|
167
168
|
"must not contain '/'."
|
168
169
|
end
|
169
|
-
|
170
|
-
|
171
|
-
Google::Cloud::Firestore::V1::StructuredQuery::CollectionSelector.new(
|
172
|
-
collection_id: collection_id, all_descendants: true
|
173
|
-
)
|
174
|
-
]
|
175
|
-
)
|
176
|
-
|
177
|
-
Query.start query, service.documents_path, self
|
170
|
+
|
171
|
+
CollectionGroup.from_collection_id service.documents_path, collection_id, self
|
178
172
|
end
|
179
173
|
alias collection_group col_group
|
180
174
|
|
@@ -256,7 +250,7 @@ module Google
|
|
256
250
|
ensure_service!
|
257
251
|
|
258
252
|
unless block_given?
|
259
|
-
return enum_for :get_all, docs, field_mask: field_mask
|
253
|
+
return enum_for :get_all, *docs, field_mask: field_mask
|
260
254
|
end
|
261
255
|
|
262
256
|
doc_paths = Array(docs).flatten.map do |doc_path|
|
@@ -634,9 +628,9 @@ module Google
|
|
634
628
|
commit_return = transaction.commit
|
635
629
|
# Conditional return value, depending on truthy commit_response
|
636
630
|
commit_response ? commit_return : transaction_return
|
637
|
-
rescue Google::Cloud::UnavailableError =>
|
631
|
+
rescue Google::Cloud::UnavailableError => e
|
638
632
|
# Re-raise if retried more than the max
|
639
|
-
raise
|
633
|
+
raise e if backoff[:current] > backoff[:max]
|
640
634
|
|
641
635
|
# Sleep with incremental backoff before restarting
|
642
636
|
sleep backoff[:delay]
|
@@ -649,18 +643,18 @@ module Google
|
|
649
643
|
transaction = Transaction.from_client \
|
650
644
|
self, previous_transaction: transaction.transaction_id
|
651
645
|
retry
|
652
|
-
rescue Google::Cloud::InvalidArgumentError =>
|
646
|
+
rescue Google::Cloud::InvalidArgumentError => e
|
653
647
|
# Return if a previous call was retried but ultimately succeeded
|
654
|
-
return nil if backoff[:current]
|
648
|
+
return nil if backoff[:current].positive?
|
655
649
|
|
656
650
|
# Re-raise error.
|
657
|
-
raise
|
658
|
-
rescue StandardError =>
|
651
|
+
raise e
|
652
|
+
rescue StandardError => e
|
659
653
|
# Rollback transaction when handling unexpected error
|
660
654
|
transaction.rollback rescue nil
|
661
655
|
|
662
656
|
# Re-raise error.
|
663
|
-
raise
|
657
|
+
raise e
|
664
658
|
end
|
665
659
|
end
|
666
660
|
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# Copyright 2021 Google LLC
|
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
|
+
# https://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
|
+
|
15
|
+
|
16
|
+
require "google/cloud/firestore/v1"
|
17
|
+
require "google/cloud/firestore/query"
|
18
|
+
require "google/cloud/firestore/query_partition"
|
19
|
+
|
20
|
+
module Google
|
21
|
+
module Cloud
|
22
|
+
module Firestore
|
23
|
+
##
|
24
|
+
# # CollectionGroup
|
25
|
+
#
|
26
|
+
# A collection group object is used for adding documents, getting
|
27
|
+
# document references, and querying for documents, including with partitions.
|
28
|
+
#
|
29
|
+
# See {Client#col_group} and {Query}.
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# require "google/cloud/firestore"
|
33
|
+
#
|
34
|
+
# firestore = Google::Cloud::Firestore.new
|
35
|
+
#
|
36
|
+
# # Get a collection group
|
37
|
+
# col_group = firestore.col_group "cities"
|
38
|
+
#
|
39
|
+
# # Get and print all city documents
|
40
|
+
# col_group.get do |city|
|
41
|
+
# puts "#{city.document_id} has #{city[:population]} residents."
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
class CollectionGroup < Query
|
45
|
+
##
|
46
|
+
# Partitions a query by returning partition cursors that can be used to run the query in parallel. The returned
|
47
|
+
# partition cursors are split points that can be used as starting/end points for the query results.
|
48
|
+
#
|
49
|
+
# @param [Integer] partition_count The desired maximum number of partition points. The number must be strictly
|
50
|
+
# positive. The actual number of partitions returned may be fewer.
|
51
|
+
#
|
52
|
+
# @return [Array<QueryPartition>] An ordered array of query partitions.
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# require "google/cloud/firestore"
|
56
|
+
#
|
57
|
+
# firestore = Google::Cloud::Firestore.new
|
58
|
+
#
|
59
|
+
# col_group = firestore.col_group "cities"
|
60
|
+
#
|
61
|
+
# partitions = col_group.partitions 3
|
62
|
+
#
|
63
|
+
# queries = partitions.map(&:to_query)
|
64
|
+
#
|
65
|
+
def partitions partition_count
|
66
|
+
ensure_service!
|
67
|
+
|
68
|
+
raise ArgumentError, "partition_count must be > 0" unless partition_count.positive?
|
69
|
+
|
70
|
+
# Partition queries require explicit ordering by __name__.
|
71
|
+
query_with_default_order = order "__name__"
|
72
|
+
# Since we are always returning an extra partition (with en empty endBefore cursor), we reduce the desired
|
73
|
+
# partition count by one.
|
74
|
+
partition_count -= 1
|
75
|
+
|
76
|
+
grpc_partitions = if partition_count.positive?
|
77
|
+
# Retrieve all pages, since cursor order is not guaranteed and they must be sorted.
|
78
|
+
list_all partition_count, query_with_default_order
|
79
|
+
else
|
80
|
+
[] # Ensure that a single, empty QueryPartition is returned.
|
81
|
+
end
|
82
|
+
cursor_values = grpc_partitions.map do |cursor|
|
83
|
+
# Convert each cursor to a (single-element) array of Google::Cloud::Firestore::DocumentReference.
|
84
|
+
cursor.values.map do |value|
|
85
|
+
Convert.value_to_raw value, client
|
86
|
+
end
|
87
|
+
end
|
88
|
+
# Sort the values of the returned cursor, which right now should only contain a single reference value (which
|
89
|
+
# needs to be sorted one component at a time).
|
90
|
+
cursor_values.sort! do |a, b|
|
91
|
+
a.first <=> b.first
|
92
|
+
end
|
93
|
+
|
94
|
+
start_at = nil
|
95
|
+
results = cursor_values.map do |end_before|
|
96
|
+
partition = QueryPartition.new query_with_default_order, start_at, end_before
|
97
|
+
start_at = end_before
|
98
|
+
partition
|
99
|
+
end
|
100
|
+
# Always add a final QueryPartition with an empty end_before value.
|
101
|
+
results << QueryPartition.new(query_with_default_order, start_at, nil)
|
102
|
+
results
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# @private New Collection group object from a path.
|
107
|
+
def self.from_collection_id parent_path, collection_id, client
|
108
|
+
query = Google::Cloud::Firestore::V1::StructuredQuery.new(
|
109
|
+
from: [
|
110
|
+
Google::Cloud::Firestore::V1::StructuredQuery::CollectionSelector.new(
|
111
|
+
collection_id: collection_id,
|
112
|
+
all_descendants: true
|
113
|
+
)
|
114
|
+
]
|
115
|
+
)
|
116
|
+
CollectionGroup.new query, parent_path, client
|
117
|
+
end
|
118
|
+
|
119
|
+
protected
|
120
|
+
|
121
|
+
def list_all partition_count, query_with_default_order
|
122
|
+
grpc_partitions = []
|
123
|
+
token = nil
|
124
|
+
loop do
|
125
|
+
grpc = service.partition_query parent_path, query_with_default_order.query, partition_count, token: token
|
126
|
+
grpc_partitions += Array(grpc.partitions)
|
127
|
+
token = grpc.next_page_token
|
128
|
+
token = nil if token == ""
|
129
|
+
break unless token
|
130
|
+
end
|
131
|
+
grpc_partitions
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -14,9 +14,9 @@
|
|
14
14
|
|
15
15
|
|
16
16
|
require "google/cloud/firestore/v1"
|
17
|
+
require "google/cloud/firestore/query"
|
17
18
|
require "google/cloud/firestore/document_reference"
|
18
19
|
require "google/cloud/firestore/document_snapshot"
|
19
|
-
require "google/cloud/firestore/query"
|
20
20
|
require "google/cloud/firestore/generate"
|
21
21
|
require "google/cloud/firestore/collection_reference_list"
|
22
22
|
|
@@ -47,6 +47,13 @@ module Google
|
|
47
47
|
# @private The firestore client object.
|
48
48
|
attr_accessor :client
|
49
49
|
|
50
|
+
##
|
51
|
+
# @private Creates a new CollectionReference.
|
52
|
+
def initialize query, path, client
|
53
|
+
super query, nil, client # Pass nil parent_path arg since this class implements #parent_path
|
54
|
+
@path = path
|
55
|
+
end
|
56
|
+
|
50
57
|
##
|
51
58
|
# The collection identifier for the collection resource.
|
52
59
|
#
|
@@ -257,11 +264,7 @@ module Google
|
|
257
264
|
]
|
258
265
|
)
|
259
266
|
|
260
|
-
new
|
261
|
-
c.client = client
|
262
|
-
c.instance_variable_set :@path, path
|
263
|
-
c.instance_variable_set :@query, query
|
264
|
-
end
|
267
|
+
CollectionReference.new query, path, client
|
265
268
|
end
|
266
269
|
|
267
270
|
protected
|
@@ -90,17 +90,17 @@ module Google
|
|
90
90
|
# collection_reference.collection_id
|
91
91
|
# end
|
92
92
|
#
|
93
|
-
def all request_limit: nil
|
93
|
+
def all request_limit: nil, &block
|
94
94
|
request_limit = request_limit.to_i if request_limit
|
95
95
|
unless block_given?
|
96
96
|
return enum_for :all, request_limit: request_limit
|
97
97
|
end
|
98
98
|
results = self
|
99
99
|
loop do
|
100
|
-
results.each
|
100
|
+
results.each(&block)
|
101
101
|
if request_limit
|
102
102
|
request_limit -= 1
|
103
|
-
break if request_limit
|
103
|
+
break if request_limit.negative?
|
104
104
|
end
|
105
105
|
break unless results.next?
|
106
106
|
results = results.next
|