google-cloud-firestore 2.5.1 → 2.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AUTHENTICATION.md +2 -1
- data/CHANGELOG.md +29 -0
- data/lib/google/cloud/firestore/client.rb +25 -20
- 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/document_reference/list.rb +1 -1
- data/lib/google/cloud/firestore/document_reference.rb +7 -0
- data/lib/google/cloud/firestore/field_path.rb +3 -7
- data/lib/google/cloud/firestore/field_value.rb +7 -2
- data/lib/google/cloud/firestore/query.rb +77 -9
- 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 +14 -0
- data/lib/google/cloud/firestore/version.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43a875c5288189790070d70828e54d6a4d094979c0f2443c557a6e4fd3de1915
|
4
|
+
data.tar.gz: 982a614359a38a6227d8498a5d36f8fe49f2a198c7c9b3561b8e2d24bec07476
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb4b447824f289da585555d5210a4672872b7b8e99ca5c5c4a02577637b7d74565da923adb1ae2776d888645c2836e785a70f6080acdc0541c35482fd1dfbd08
|
7
|
+
data.tar.gz: 4a0641708dee2f1b923aeb3bf2aeca4b7517bd45fca9762376c2b1b16bf3cb1c8cd7b96956498c9031ec52c15662d1b9ea88e4f828cbb5f907a17ad7d54be41e
|
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,34 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 2.6.3 / 2021-08-24
|
4
|
+
|
5
|
+
#### Bug Fixes
|
6
|
+
|
7
|
+
* Fix transaction retry behavior
|
8
|
+
|
9
|
+
### 2.6.2 / 2021-07-26
|
10
|
+
|
11
|
+
#### Bug Fixes
|
12
|
+
|
13
|
+
* Update FieldPath#formatted_string to correctly escape non-simple characters
|
14
|
+
|
15
|
+
### 2.6.1 / 2021-07-08
|
16
|
+
|
17
|
+
#### Documentation
|
18
|
+
|
19
|
+
* Update AUTHENTICATION.md in handwritten packages
|
20
|
+
|
21
|
+
### 2.6.0 / 2021-06-15
|
22
|
+
|
23
|
+
#### Features
|
24
|
+
|
25
|
+
* Add support for Query Partitions
|
26
|
+
* Add CollectionGroup
|
27
|
+
* Update Client#col_group to return CollectionGroup (subclass of Query)
|
28
|
+
* Add QueryPartition
|
29
|
+
* Add QueryPartition::List
|
30
|
+
* Add Query#to_json and Query.from_json
|
31
|
+
|
3
32
|
### 2.5.1 / 2021-04-19
|
4
33
|
|
5
34
|
#### Bug Fixes
|
@@ -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
|
|
@@ -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
|
|
@@ -634,7 +628,24 @@ 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::
|
631
|
+
rescue Google::Cloud::AbortedError,
|
632
|
+
Google::Cloud::CanceledError,
|
633
|
+
Google::Cloud::UnknownError,
|
634
|
+
Google::Cloud::DeadlineExceededError,
|
635
|
+
Google::Cloud::InternalError,
|
636
|
+
Google::Cloud::UnauthenticatedError,
|
637
|
+
Google::Cloud::ResourceExhaustedError,
|
638
|
+
Google::Cloud::UnavailableError,
|
639
|
+
Google::Cloud::InvalidArgumentError => e
|
640
|
+
|
641
|
+
if e.instance_of? Google::Cloud::InvalidArgumentError
|
642
|
+
# Return if a previous call was retried but ultimately succeeded
|
643
|
+
return nil if backoff[:current].positive?
|
644
|
+
# The Firestore backend uses "INVALID_ARGUMENT" for transaction IDs that have expired.
|
645
|
+
# While INVALID_ARGUMENT is generally not retryable, we retry this specific case.
|
646
|
+
raise e unless e.message =~ /transaction has expired/
|
647
|
+
end
|
648
|
+
|
638
649
|
# Re-raise if retried more than the max
|
639
650
|
raise e if backoff[:current] > backoff[:max]
|
640
651
|
|
@@ -649,12 +660,6 @@ module Google
|
|
649
660
|
transaction = Transaction.from_client \
|
650
661
|
self, previous_transaction: transaction.transaction_id
|
651
662
|
retry
|
652
|
-
rescue Google::Cloud::InvalidArgumentError => e
|
653
|
-
# Return if a previous call was retried but ultimately succeeded
|
654
|
-
return nil if backoff[:current].positive?
|
655
|
-
|
656
|
-
# Re-raise error.
|
657
|
-
raise e
|
658
663
|
rescue StandardError => e
|
659
664
|
# Rollback transaction when handling unexpected error
|
660
665
|
transaction.rollback rescue nil
|
@@ -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
|
@@ -109,7 +109,7 @@ module Google
|
|
109
109
|
#
|
110
110
|
# @return [Enumerator]
|
111
111
|
#
|
112
|
-
# @example Iterating each document reference by passing a block:
|
112
|
+
# @example Iterating each document reference by passing a block or proc:
|
113
113
|
# require "google/cloud/firestore"
|
114
114
|
#
|
115
115
|
# firestore = Google::Cloud::Firestore.new
|
@@ -18,6 +18,7 @@ require "google/cloud/firestore/document_snapshot"
|
|
18
18
|
require "google/cloud/firestore/collection_reference"
|
19
19
|
require "google/cloud/firestore/document_listener"
|
20
20
|
require "google/cloud/firestore/document_reference/list"
|
21
|
+
require "google/cloud/firestore/resource_path"
|
21
22
|
|
22
23
|
module Google
|
23
24
|
module Cloud
|
@@ -459,6 +460,12 @@ module Google
|
|
459
460
|
|
460
461
|
# @!endgroup
|
461
462
|
|
463
|
+
# @private
|
464
|
+
def <=> other
|
465
|
+
return nil unless other.is_a? self.class
|
466
|
+
ResourcePath.from_path(path) <=> ResourcePath.from_path(other.path)
|
467
|
+
end
|
468
|
+
|
462
469
|
##
|
463
470
|
# @private New DocumentReference object from a path.
|
464
471
|
def self.from_path path, client
|
@@ -209,19 +209,15 @@ module Google
|
|
209
209
|
|
210
210
|
protected
|
211
211
|
|
212
|
-
START_FIELD_PATH_CHARS = /\A[a-zA-Z_]/.freeze
|
213
212
|
INVALID_FIELD_PATH_CHARS = %r{[~*/\[\]]}.freeze
|
213
|
+
SIMPLE_FIELD_PATH_CHARS = /\A[_a-zA-Z][_a-zA-Z0-9]*\Z/.freeze
|
214
214
|
|
215
215
|
def escape_field_for_path field
|
216
216
|
field = String field
|
217
217
|
|
218
|
-
if
|
219
|
-
field["."] || field["`"] || field["\\"]
|
220
|
-
escaped_field = field.gsub(/[`\\]/, "`" => "\\\`", "\\" => "\\\\")
|
221
|
-
return "`#{escaped_field}`"
|
222
|
-
end
|
218
|
+
return field if SIMPLE_FIELD_PATH_CHARS.match field
|
223
219
|
|
224
|
-
|
220
|
+
field = field.gsub(/[`\\]/, "`" => "\\`", "\\" => "\\\\")
|
225
221
|
|
226
222
|
"`#{field}`"
|
227
223
|
end
|
@@ -27,9 +27,14 @@ module Google
|
|
27
27
|
#
|
28
28
|
# firestore = Google::Cloud::Firestore.new
|
29
29
|
#
|
30
|
-
#
|
30
|
+
# # Get a document reference
|
31
|
+
# nyc_ref = firestore.doc "cities/NYC"
|
31
32
|
#
|
32
|
-
# #
|
33
|
+
# # Set the population to increment by 1.
|
34
|
+
# increment_value = Google::Cloud::Firestore::FieldValue.increment 1
|
35
|
+
#
|
36
|
+
# nyc_ref.update({ name: "New York City",
|
37
|
+
# population: increment_value })
|
33
38
|
#
|
34
39
|
class FieldValue
|
35
40
|
##
|
@@ -17,6 +17,7 @@ require "google/cloud/firestore/v1"
|
|
17
17
|
require "google/cloud/firestore/document_snapshot"
|
18
18
|
require "google/cloud/firestore/query_listener"
|
19
19
|
require "google/cloud/firestore/convert"
|
20
|
+
require "json"
|
20
21
|
|
21
22
|
module Google
|
22
23
|
module Cloud
|
@@ -74,6 +75,16 @@ module Google
|
|
74
75
|
# @private The firestore client object.
|
75
76
|
attr_accessor :client
|
76
77
|
|
78
|
+
##
|
79
|
+
# @private Creates a new Query.
|
80
|
+
def initialize query, parent_path, client, limit_type: nil
|
81
|
+
query ||= StructuredQuery.new
|
82
|
+
@query = query
|
83
|
+
@parent_path = parent_path
|
84
|
+
@limit_type = limit_type
|
85
|
+
@client = client
|
86
|
+
end
|
87
|
+
|
77
88
|
##
|
78
89
|
# Restricts documents matching the query to return only data for the
|
79
90
|
# provided fields.
|
@@ -962,16 +973,71 @@ module Google
|
|
962
973
|
end
|
963
974
|
alias on_snapshot listen
|
964
975
|
|
976
|
+
##
|
977
|
+
# Serializes the instance to a JSON text string. See also {Query.from_json}.
|
978
|
+
#
|
979
|
+
# @return [String] A JSON text string.
|
980
|
+
#
|
981
|
+
# @example
|
982
|
+
# require "google/cloud/firestore"
|
983
|
+
#
|
984
|
+
# firestore = Google::Cloud::Firestore.new
|
985
|
+
# query = firestore.col(:cities).select(:population)
|
986
|
+
#
|
987
|
+
# json = query.to_json
|
988
|
+
#
|
989
|
+
# new_query = Google::Cloud::Firestore::Query.from_json json, firestore
|
990
|
+
#
|
991
|
+
# new_query.get do |city|
|
992
|
+
# puts "#{city.document_id} has #{city[:population]} residents."
|
993
|
+
# end
|
994
|
+
#
|
995
|
+
def to_json options = nil
|
996
|
+
query_json = Google::Cloud::Firestore::V1::StructuredQuery.encode_json query
|
997
|
+
{
|
998
|
+
"query" => JSON.parse(query_json),
|
999
|
+
"parent_path" => parent_path,
|
1000
|
+
"limit_type" => limit_type
|
1001
|
+
}.to_json options
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
##
|
1005
|
+
# Deserializes a JSON text string serialized from this class and returns it as a new instance. See also
|
1006
|
+
# {#to_json}.
|
1007
|
+
#
|
1008
|
+
# @param [String] json A JSON text string serialized using {#to_json}.
|
1009
|
+
# @param [Google::Cloud::Firestore::Client] client A connected client instance.
|
1010
|
+
#
|
1011
|
+
# @return [Query] A new query equal to the original query used to create the JSON text string.
|
1012
|
+
#
|
1013
|
+
# @example
|
1014
|
+
# require "google/cloud/firestore"
|
1015
|
+
#
|
1016
|
+
# firestore = Google::Cloud::Firestore.new
|
1017
|
+
# query = firestore.col(:cities).select(:population)
|
1018
|
+
#
|
1019
|
+
# json = query.to_json
|
1020
|
+
#
|
1021
|
+
# new_query = Google::Cloud::Firestore::Query.from_json json, firestore
|
1022
|
+
#
|
1023
|
+
# new_query.get do |city|
|
1024
|
+
# puts "#{city.document_id} has #{city[:population]} residents."
|
1025
|
+
# end
|
1026
|
+
#
|
1027
|
+
def self.from_json json, client
|
1028
|
+
raise ArgumentError, "client is required" unless client
|
1029
|
+
|
1030
|
+
json = JSON.parse json
|
1031
|
+
query_json = json["query"]
|
1032
|
+
raise ArgumentError, "Field 'query' is required" unless query_json
|
1033
|
+
query = Google::Cloud::Firestore::V1::StructuredQuery.decode_json query_json.to_json
|
1034
|
+
start query, json["parent_path"], client, limit_type: json["limit_type"]&.to_sym
|
1035
|
+
end
|
1036
|
+
|
965
1037
|
##
|
966
1038
|
# @private Start a new Query.
|
967
1039
|
def self.start query, parent_path, client, limit_type: nil
|
968
|
-
query
|
969
|
-
Query.new.tap do |q|
|
970
|
-
q.instance_variable_set :@query, query
|
971
|
-
q.instance_variable_set :@parent_path, parent_path
|
972
|
-
q.instance_variable_set :@limit_type, limit_type
|
973
|
-
q.instance_variable_set :@client, client
|
974
|
-
end
|
1040
|
+
new query, parent_path, client, limit_type: limit_type
|
975
1041
|
end
|
976
1042
|
|
977
1043
|
protected
|
@@ -1094,11 +1160,14 @@ module Google
|
|
1094
1160
|
return snapshot_to_cursor values.first, query
|
1095
1161
|
end
|
1096
1162
|
|
1163
|
+
# The *values param in start_at, start_after, etc. will wrap an array argument in an array, so unwrap it here.
|
1164
|
+
values = values.first if values.count == 1 && values.first.is_a?(Array)
|
1165
|
+
|
1097
1166
|
# pair values with their field_paths to ensure correct formatting
|
1098
1167
|
order_field_paths = order_by_field_paths query
|
1099
1168
|
if values.count > order_field_paths.count
|
1100
1169
|
# raise if too many values provided for the cursor
|
1101
|
-
raise ArgumentError, "
|
1170
|
+
raise ArgumentError, "There cannot be more cursor values than order by fields"
|
1102
1171
|
end
|
1103
1172
|
|
1104
1173
|
values = values.zip(order_field_paths).map do |value, field_path|
|
@@ -1130,7 +1199,6 @@ module Google
|
|
1130
1199
|
snapshot[field_path]
|
1131
1200
|
end
|
1132
1201
|
end
|
1133
|
-
|
1134
1202
|
values_to_cursor values, query
|
1135
1203
|
end
|
1136
1204
|
|
@@ -0,0 +1,80 @@
|
|
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
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Firestore
|
19
|
+
##
|
20
|
+
# # QueryPartition
|
21
|
+
#
|
22
|
+
# Represents a split point that can be used in a query as a starting and/or end point for the query results.
|
23
|
+
#
|
24
|
+
# The cursors returned by {#start_at} and {#end_before} can only be used in a query that matches the constraint of
|
25
|
+
# the query that produced this partition.
|
26
|
+
#
|
27
|
+
# See {CollectionGroup#partitions} and {Query}.
|
28
|
+
#
|
29
|
+
# @!attribute [r] start_at
|
30
|
+
# The cursor values that define the first result for this partition, or `nil` if this is the first partition.
|
31
|
+
# Returns an array of values that represent a position, in the order they appear in the order by clause of the
|
32
|
+
# query. Can contain fewer values than specified in the order by clause. Will be used in the query returned by
|
33
|
+
# {#to_query}.
|
34
|
+
# @return [Array<Object>, nil] Typically, the values are {DocumentReference} objects.
|
35
|
+
# @!attribute [r] end_before
|
36
|
+
# The cursor values that define the first result after this partition, or `nil` if this is the last partition.
|
37
|
+
# Returns an array of values that represent a position, in the order they appear in the order by clause of the
|
38
|
+
# query. Can contain fewer values than specified in the order by clause. Will be used in the query returned by
|
39
|
+
# {#to_query}.
|
40
|
+
# @return [Array<Object>, nil] Typically, the values are {DocumentReference} objects.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# require "google/cloud/firestore"
|
44
|
+
#
|
45
|
+
# firestore = Google::Cloud::Firestore.new
|
46
|
+
#
|
47
|
+
# col_group = firestore.col_group "cities"
|
48
|
+
#
|
49
|
+
# partitions = col_group.partitions 3
|
50
|
+
#
|
51
|
+
# queries = partitions.map(&:to_query)
|
52
|
+
#
|
53
|
+
class QueryPartition
|
54
|
+
attr_reader :start_at
|
55
|
+
attr_reader :end_before
|
56
|
+
|
57
|
+
##
|
58
|
+
# @private New QueryPartition from query and Cursor
|
59
|
+
def initialize query, start_at, end_before
|
60
|
+
@query = query
|
61
|
+
@start_at = start_at
|
62
|
+
@end_before = end_before
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Creates a new query that only returns the documents for this partition, using the cursor values from
|
67
|
+
# {#start_at} and {#end_before}.
|
68
|
+
#
|
69
|
+
# @return [Query] The query for the partition.
|
70
|
+
#
|
71
|
+
def to_query
|
72
|
+
base_query = @query
|
73
|
+
base_query = base_query.start_at start_at if start_at
|
74
|
+
base_query = base_query.end_before end_before if end_before
|
75
|
+
base_query
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,58 @@
|
|
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
|
+
module Google
|
17
|
+
module Cloud
|
18
|
+
module Firestore
|
19
|
+
##
|
20
|
+
# @private
|
21
|
+
#
|
22
|
+
# Represents a resource path to the Firestore API.
|
23
|
+
#
|
24
|
+
class ResourcePath
|
25
|
+
include Comparable
|
26
|
+
|
27
|
+
RESOURCE_PATH_RE = %r{^projects/([^/]*)/databases/([^/]*)(?:/documents/)?([\s\S]*)$}.freeze
|
28
|
+
|
29
|
+
attr_reader :project_id
|
30
|
+
attr_reader :database_id
|
31
|
+
attr_reader :segments
|
32
|
+
|
33
|
+
##
|
34
|
+
# Creates a resource path object.
|
35
|
+
#
|
36
|
+
# @param [Array<String>] segments One or more strings representing the resource path.
|
37
|
+
#
|
38
|
+
# @return [ResourcePath] The resource path object.
|
39
|
+
#
|
40
|
+
def initialize project_id, database_id, segments
|
41
|
+
@project_id = project_id
|
42
|
+
@database_id = database_id
|
43
|
+
@segments = segments.split "/"
|
44
|
+
end
|
45
|
+
|
46
|
+
def <=> other
|
47
|
+
return nil unless other.is_a? ResourcePath
|
48
|
+
[project_id, database_id, segments] <=> [other.project_id, other.database_id, other.segments]
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.from_path path
|
52
|
+
data = RESOURCE_PATH_RE.match path
|
53
|
+
new data[1], data[2], data[3]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -96,6 +96,20 @@ module Google
|
|
96
96
|
)
|
97
97
|
end
|
98
98
|
|
99
|
+
##
|
100
|
+
# Returns Google::Cloud::Firestore::V1::PartitionQueryResponse
|
101
|
+
def partition_query parent, query_grpc, partition_count, token: nil, max: nil
|
102
|
+
request = Google::Cloud::Firestore::V1::PartitionQueryRequest.new(
|
103
|
+
parent: parent,
|
104
|
+
structured_query: query_grpc,
|
105
|
+
partition_count: partition_count,
|
106
|
+
page_token: token,
|
107
|
+
page_size: max
|
108
|
+
)
|
109
|
+
paged_enum = firestore.partition_query request
|
110
|
+
paged_enum.response
|
111
|
+
end
|
112
|
+
|
99
113
|
def run_query path, query_grpc, transaction: nil
|
100
114
|
run_query_req = {
|
101
115
|
parent: path,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-cloud-firestore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Google Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-cloud-core
|
@@ -227,6 +227,7 @@ files:
|
|
227
227
|
- lib/google/cloud/firestore.rb
|
228
228
|
- lib/google/cloud/firestore/batch.rb
|
229
229
|
- lib/google/cloud/firestore/client.rb
|
230
|
+
- lib/google/cloud/firestore/collection_group.rb
|
230
231
|
- lib/google/cloud/firestore/collection_reference.rb
|
231
232
|
- lib/google/cloud/firestore/collection_reference_list.rb
|
232
233
|
- lib/google/cloud/firestore/commit_response.rb
|
@@ -242,7 +243,9 @@ files:
|
|
242
243
|
- lib/google/cloud/firestore/generate.rb
|
243
244
|
- lib/google/cloud/firestore/query.rb
|
244
245
|
- lib/google/cloud/firestore/query_listener.rb
|
246
|
+
- lib/google/cloud/firestore/query_partition.rb
|
245
247
|
- lib/google/cloud/firestore/query_snapshot.rb
|
248
|
+
- lib/google/cloud/firestore/resource_path.rb
|
246
249
|
- lib/google/cloud/firestore/service.rb
|
247
250
|
- lib/google/cloud/firestore/transaction.rb
|
248
251
|
- lib/google/cloud/firestore/version.rb
|
@@ -269,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
269
272
|
- !ruby/object:Gem::Version
|
270
273
|
version: '0'
|
271
274
|
requirements: []
|
272
|
-
rubygems_version: 3.2.
|
275
|
+
rubygems_version: 3.2.17
|
273
276
|
signing_key:
|
274
277
|
specification_version: 4
|
275
278
|
summary: API Client library for Google Cloud Firestore API
|