google-cloud-firestore 2.7.2 → 2.15.0

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHENTICATION.md +8 -26
  3. data/CHANGELOG.md +69 -0
  4. data/LOGGING.md +1 -1
  5. data/lib/google/cloud/firestore/aggregate_query.rb +285 -0
  6. data/lib/google/cloud/firestore/aggregate_query_snapshot.rb +145 -0
  7. data/lib/google/cloud/firestore/bulk_commit_batch.rb +73 -0
  8. data/lib/google/cloud/firestore/bulk_writer.rb +558 -0
  9. data/lib/google/cloud/firestore/bulk_writer_exception.rb +40 -0
  10. data/lib/google/cloud/firestore/bulk_writer_operation.rb +126 -0
  11. data/lib/google/cloud/firestore/bulk_writer_scheduler.rb +164 -0
  12. data/lib/google/cloud/firestore/client.rb +161 -10
  13. data/lib/google/cloud/firestore/collection_group.rb +20 -4
  14. data/lib/google/cloud/firestore/collection_reference.rb +17 -2
  15. data/lib/google/cloud/firestore/collection_reference_list.rb +4 -3
  16. data/lib/google/cloud/firestore/convert.rb +6 -7
  17. data/lib/google/cloud/firestore/document_reference/list.rb +5 -3
  18. data/lib/google/cloud/firestore/document_reference.rb +20 -3
  19. data/lib/google/cloud/firestore/document_snapshot.rb +1 -1
  20. data/lib/google/cloud/firestore/errors.rb +60 -0
  21. data/lib/google/cloud/firestore/filter.rb +326 -0
  22. data/lib/google/cloud/firestore/promise/future.rb +97 -0
  23. data/lib/google/cloud/firestore/query.rb +112 -89
  24. data/lib/google/cloud/firestore/rate_limiter.rb +80 -0
  25. data/lib/google/cloud/firestore/service.rb +74 -23
  26. data/lib/google/cloud/firestore/transaction.rb +57 -4
  27. data/lib/google/cloud/firestore/version.rb +1 -1
  28. data/lib/google/cloud/firestore.rb +17 -7
  29. data/lib/google-cloud-firestore.rb +45 -8
  30. metadata +17 -146
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0cb9b1838e2d0de1dd7a122b6395a7506e1c9ffdc237edc88ece03b38902694d
4
- data.tar.gz: 92cd04357a9295dec00b34c748cf0e1a9b7f44165915d41e8dac3b5eff40ef84
3
+ metadata.gz: 16163a09797c60820b760bb85283dc3ab8532aacc329dbdf0e8672ab7b8e4066
4
+ data.tar.gz: a502101923eaeffb2b8ca9112134ffc14e8971970509cb9f34e5263c5889a791
5
5
  SHA512:
6
- metadata.gz: 3fc0b6e13ba161fc579a969fdf3848621d8aaf45bdd6e64fa5ad2dc2a4d4efd4a934034724f03f7bdc7b2fb50a4976ea3c3fb6dbc99576ef274bbf435e1d0e02
7
- data.tar.gz: 465c31a8a2a581f90107b305d0d465e4e8c4da368c5b00651075b45031708a38e47e3e7a2deae8bacae32b8f8779ca164b68a5a99dfec1f6d0832d1f70d67089
6
+ metadata.gz: 06e1cb717e9ccdb4560f66d38af4845610aaed131557956d5dea7c86a97169c7f7af979e956ef53a7ac3ce36f19ade87c3a00a7f568bcdc2ea82aaf77dfafb77
7
+ data.tar.gz: 388eb390a647550643bdce6c1a0b57bcb98fa9ad63fdb24808971dafeac3342ac6a0943bc86103d892b9a4e572746ec01ddf167f9629ff29df768bedcc606c59
data/AUTHENTICATION.md CHANGED
@@ -124,15 +124,6 @@ To configure your system for this, simply:
124
124
  **NOTE:** This is _not_ recommended for running in production. The Cloud SDK
125
125
  *should* only be used during development.
126
126
 
127
- [gce-how-to]: https://cloud.google.com/compute/docs/authentication#using
128
- [dev-console]: https://console.cloud.google.com/project
129
-
130
- [enable-apis]: https://raw.githubusercontent.com/GoogleCloudPlatform/gcloud-common/master/authentication/enable-apis.png
131
-
132
- [create-new-service-account]: https://raw.githubusercontent.com/GoogleCloudPlatform/gcloud-common/master/authentication/create-new-service-account.png
133
- [create-new-service-account-existing-keys]: https://raw.githubusercontent.com/GoogleCloudPlatform/gcloud-common/master/authentication/create-new-service-account-existing-keys.png
134
- [reuse-service-account]: https://raw.githubusercontent.com/GoogleCloudPlatform/gcloud-common/master/authentication/reuse-service-account.png
135
-
136
127
  ## Creating a Service Account
137
128
 
138
129
  Google Cloud requires a **Project ID** and **Service Account Credentials** to
@@ -143,31 +134,22 @@ If you are not running this client within [Google Cloud Platform
143
134
  environments](#google-cloud-platform-environments), you need a Google
144
135
  Developers service account.
145
136
 
146
- 1. Visit the [Google Developers Console][dev-console].
137
+ 1. Visit the [Google Cloud Console](https://console.cloud.google.com/project).
147
138
  1. Create a new project or click on an existing project.
148
- 1. Activate the slide-out navigation tray and select **API Manager**. From
139
+ 1. Activate the menu in the upper left and select **APIs & Services**. From
149
140
  here, you will enable the APIs that your application requires.
150
141
 
151
- ![Enable the APIs that your application requires][enable-apis]
152
-
153
142
  *Note: You may need to enable billing in order to use these services.*
154
143
 
155
144
  1. Select **Credentials** from the side navigation.
156
145
 
157
- You should see a screen like one of the following.
158
-
159
- ![Create a new service account][create-new-service-account]
160
-
161
- ![Create a new service account With Existing Keys][create-new-service-account-existing-keys]
162
-
163
- Find the "Add credentials" drop down and select "Service account" to be
164
- guided through downloading a new JSON key file.
165
-
166
- If you want to re-use an existing service account, you can easily generate a
167
- new key file. Just select the account you wish to re-use, and click "Generate
168
- new JSON key":
146
+ Find the "Create credentials" drop down near the top of the page, and select
147
+ "Service account" to be guided through downloading a new JSON key file.
169
148
 
170
- ![Re-use an existing service account][reuse-service-account]
149
+ If you want to re-use an existing service account, you can easily generate
150
+ a new key file. Just select the account you wish to re-use click the pencil
151
+ tool on the right side to edit the service account, select the **Keys** tab,
152
+ and then select **Add Key**.
171
153
 
172
154
  The key file you download will be used by this library to authenticate API
173
155
  requests and should be stored in a secure location.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,74 @@
1
1
  # Release History
2
2
 
3
+ ### 2.15.0 (2024-03-07)
4
+
5
+ #### Features
6
+
7
+ * Update minimum supported Ruby version to 2.7 ([#25298](https://github.com/googleapis/google-cloud-ruby/issues/25298))
8
+
9
+ ### 2.14.0 (2024-01-31)
10
+
11
+ #### Features
12
+
13
+ * Support sum & avg aggregate functions ([#23446](https://github.com/googleapis/google-cloud-ruby/issues/23446))
14
+
15
+ ### 2.13.1 (2023-06-16)
16
+
17
+ #### Documentation
18
+
19
+ * Fixed broken links in authentication documentation ([#21619](https://github.com/googleapis/google-cloud-ruby/issues/21619))
20
+
21
+ ### 2.13.0 (2023-05-10)
22
+
23
+ #### Features
24
+
25
+ * Added support for bulk writer ([#21426](https://github.com/googleapis/google-cloud-ruby/issues/21426))
26
+
27
+ ### 2.12.0 (2023-04-20)
28
+
29
+ #### Features
30
+
31
+ * Add support for OR query ([#20920](https://github.com/googleapis/google-cloud-ruby/issues/20920))
32
+
33
+ ### 2.11.0 (2023-02-23)
34
+
35
+ #### Features
36
+
37
+ * Support REST transport ([#20446](https://github.com/googleapis/google-cloud-ruby/issues/20446))
38
+
39
+ ### 2.10.1 (2023-02-16)
40
+
41
+ #### Bug Fixes
42
+
43
+ * update version of firestore-v1 in gemspec ([#20433](https://github.com/googleapis/google-cloud-ruby/issues/20433))
44
+
45
+ ### 2.10.0 (2023-02-09)
46
+
47
+ #### Features
48
+
49
+ * Added support for multiple databases ([#20029](https://github.com/googleapis/google-cloud-ruby/issues/20029))
50
+
51
+ ### 2.9.1 (2023-02-03)
52
+
53
+ #### Bug Fixes
54
+
55
+ * Change "aggregate_alias" to optional param ([#20082](https://github.com/googleapis/google-cloud-ruby/issues/20082))
56
+
57
+ ### 2.9.0 (2023-01-26)
58
+
59
+ #### Features
60
+
61
+ * Added support for read time ([#19851](https://github.com/googleapis/google-cloud-ruby/issues/19851))
62
+
63
+ ### 2.8.0 (2023-01-05)
64
+
65
+ #### Features
66
+
67
+ * Support query count for Firestore ([#19457](https://github.com/googleapis/google-cloud-ruby/issues/19457))
68
+ #### Bug Fixes
69
+
70
+ * Add support for merging null field in a document ([#19918](https://github.com/googleapis/google-cloud-ruby/issues/19918))
71
+
3
72
  ### 2.7.2 (2022-08-24)
4
73
 
5
74
  #### Documentation
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/libdoc/logger/rdoc/Logger.html) as
6
+ [`Logger`](https://ruby-doc.org/current/stdlibs/logger/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
@@ -0,0 +1,285 @@
1
+ # Copyright 2022 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
+ require "google/cloud/firestore/v1"
16
+ require "google/cloud/firestore/aggregate_query_snapshot"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Firestore
21
+ ##
22
+ # # AggregateQuery
23
+ #
24
+ # An aggregate query can be used to fetch aggregate values (ex: count) for a query
25
+ #
26
+ # Instances of this class are immutable. All methods that refine the aggregate query
27
+ # return new instances.
28
+ #
29
+ # @example
30
+ # require "google/cloud/firestore"
31
+ #
32
+ # firestore = Google::Cloud::Firestore.new
33
+ #
34
+ # query = firestore.col "cities"
35
+ #
36
+ # # Create an aggregate query
37
+ # aggregate_query = query.aggregate_query
38
+ # .add_count
39
+ #
40
+ # aggregate_query.get do |aggregate_snapshot|
41
+ # puts aggregate_snapshot.get
42
+ # end
43
+ #
44
+ # @example Alias an aggregate query
45
+ # require "google/cloud/firestore"
46
+ #
47
+ # firestore = Google::Cloud::Firestore.new
48
+ #
49
+ # # Create a query
50
+ # query = firestore.col "cities"
51
+ #
52
+ # # Create an aggregate query
53
+ # aggregate_query = query.aggregate_query
54
+ # .add_count aggregate_alias: 'total_cities'
55
+ #
56
+ # aggregate_query.get do |aggregate_snapshot|
57
+ # puts aggregate_snapshot.get('total_cities')
58
+ # end
59
+ #
60
+ class AggregateQuery
61
+ ##
62
+ # @private The firestore client object.
63
+ attr_accessor :client
64
+
65
+ ##
66
+ # @private The type for limit queries.
67
+ attr_reader :parent_path
68
+
69
+ ##
70
+ # @private The Google::Cloud::Firestore::Query object.
71
+ attr_reader :query
72
+
73
+ ##
74
+ # @private Object of type
75
+ # Google::Cloud::Firestore::V1::StructuredAggregationQuery
76
+ attr_reader :grpc
77
+
78
+ # @private
79
+ DEFAULT_COUNT_ALIAS = "count".freeze
80
+
81
+ # @private
82
+ DEFAULT_SUM_ALIAS = "sum".freeze
83
+
84
+ # @private
85
+ DEFAULT_AVG_ALIAS = "avg".freeze
86
+
87
+ ##
88
+ # @private Creates a new AggregateQuery
89
+ def initialize query, parent_path, client
90
+ @query = query
91
+ @parent_path = parent_path
92
+ @client = client
93
+ @grpc = Google::Cloud::Firestore::V1::StructuredAggregationQuery.new(
94
+ structured_query: @query.query,
95
+ aggregations: []
96
+ )
97
+ end
98
+
99
+ ##
100
+ # Adds a count aggregate.
101
+ #
102
+ # @param aggregate_alias [String] Alias to refer to the aggregate. Optional
103
+ #
104
+ # @return [AggregateQuery] A new aggregate query with the added count aggregate.
105
+ #
106
+ # @example
107
+ # require "google/cloud/firestore"
108
+ #
109
+ # firestore = Google::Cloud::Firestore.new
110
+ #
111
+ # query = firestore.col "cities"
112
+ #
113
+ # # Create an aggregate query
114
+ # aggregate_query = query.aggregate_query
115
+ # .add_count
116
+ #
117
+ # aggregate_query.get do |aggregate_snapshot|
118
+ # puts aggregate_snapshot.get
119
+ # end
120
+ #
121
+ def add_count aggregate_alias: nil
122
+ aggregate_alias ||= DEFAULT_COUNT_ALIAS
123
+ new_aggregate = Google::Cloud::Firestore::V1::StructuredAggregationQuery::Aggregation.new(
124
+ count: Google::Cloud::Firestore::V1::StructuredAggregationQuery::Aggregation::Count.new,
125
+ alias: aggregate_alias
126
+ )
127
+
128
+ start new_aggregate
129
+ end
130
+
131
+ ##
132
+ # Adds a sum aggregate.
133
+ #
134
+ # @param field [String] The field to sum by
135
+ # @param aggregate_alias [String] Alias to refer to the aggregate
136
+ #
137
+ # @return [AggregateQuery] A new aggregate query with the added sum aggregate.
138
+ #
139
+ # @example
140
+ # require "google/cloud/firestore"
141
+ #
142
+ # firestore = Google::Cloud::Firestore.new
143
+ #
144
+ # query = firestore.col "cities"
145
+ #
146
+ # # Create an aggregate query
147
+ # aggregate_query = query.aggregate_query
148
+ # .add_sum("population")
149
+ #
150
+ # aggregate_query.get do |aggregate_snapshot|
151
+ # puts aggregate_snapshot.get
152
+ # end
153
+ #
154
+ def add_sum field, aggregate_alias: nil
155
+ aggregate_alias ||= DEFAULT_SUM_ALIAS
156
+ field = FieldPath.parse field unless field.is_a? FieldPath
157
+ new_aggregate = Google::Cloud::Firestore::V1::StructuredAggregationQuery::Aggregation.new(
158
+ sum: Google::Cloud::Firestore::V1::StructuredAggregationQuery::Aggregation::Sum.new(
159
+ field: Google::Cloud::Firestore::V1::StructuredQuery::FieldReference.new(
160
+ field_path: field.formatted_string
161
+ )
162
+ ),
163
+ alias: aggregate_alias
164
+ )
165
+
166
+ start new_aggregate
167
+ end
168
+
169
+ ##
170
+ # Adds an average aggregate.
171
+ #
172
+ # @param field [String] The field to apply average on
173
+ # @param aggregate_alias [String] Alias to refer to the aggregate
174
+ #
175
+ # @return [AggregateQuery] A new aggregate query with the added average aggregate.
176
+ #
177
+ # @example
178
+ # require "google/cloud/firestore"
179
+ #
180
+ # firestore = Google::Cloud::Firestore.new
181
+ #
182
+ # query = firestore.col "cities"
183
+ #
184
+ # # Create an aggregate query
185
+ # aggregate_query = query.aggregate_query
186
+ # .add_avg("population")
187
+ #
188
+ # aggregate_query.get do |aggregate_snapshot|
189
+ # puts aggregate_snapshot.get
190
+ # end
191
+ #
192
+ def add_avg field, aggregate_alias: nil
193
+ aggregate_alias ||= DEFAULT_AVG_ALIAS
194
+ field = FieldPath.parse field unless field.is_a? FieldPath
195
+ new_aggregate = Google::Cloud::Firestore::V1::StructuredAggregationQuery::Aggregation.new(
196
+ avg: Google::Cloud::Firestore::V1::StructuredAggregationQuery::Aggregation::Avg.new(
197
+ field: Google::Cloud::Firestore::V1::StructuredQuery::FieldReference.new(
198
+ field_path: field.formatted_string
199
+ )
200
+ ),
201
+ alias: aggregate_alias
202
+ )
203
+
204
+ start new_aggregate
205
+ end
206
+
207
+ ##
208
+ # @private
209
+ def start new_aggregate
210
+ combined_aggregates = [].concat(grpc.aggregations).push(new_aggregate)
211
+ new_grpc = Google::Cloud::Firestore::V1::StructuredAggregationQuery.new(
212
+ structured_query: @query.query,
213
+ aggregations: combined_aggregates
214
+ )
215
+ self.class.new(@query, @parent_path, @client).tap do |aq|
216
+ aq.instance_variable_set :@grpc, new_grpc
217
+ end
218
+ end
219
+
220
+ ##
221
+ # Retrieves aggregate snapshot for the query.
222
+ #
223
+ # @yield [snapshot] The block for accessing the aggregate query snapshots.
224
+ # @yieldparam [AggregateQuerySnapshot] An aggregate query snapshot.
225
+ #
226
+ # @return [Enumerator<AggregateQuerySnapshot>] A list of aggregate query snapshots.
227
+ #
228
+ # @example
229
+ # require "google/cloud/firestore"
230
+ #
231
+ # firestore = Google::Cloud::Firestore.new
232
+ #
233
+ # query = firestore.col "cities"
234
+ #
235
+ # # Create an aggregate query
236
+ # aggregate_query = query.aggregate_query
237
+ # .add_count
238
+ #
239
+ # aggregate_query.get do |aggregate_snapshot|
240
+ # puts aggregate_snapshot.get
241
+ # end
242
+ #
243
+ def get
244
+ ensure_service!
245
+
246
+ return enum_for :get unless block_given?
247
+
248
+ responses = service.run_aggregate_query @parent_path, @grpc
249
+ responses.each do |response|
250
+ next if response.result.nil?
251
+ yield AggregateQuerySnapshot.from_run_aggregate_query_response response
252
+ end
253
+ end
254
+
255
+ ##
256
+ # @private
257
+ def to_grpc
258
+ @grpc
259
+ end
260
+
261
+ protected
262
+
263
+ ##
264
+ # @private Raise an error unless a database is available.
265
+ def ensure_client!
266
+ raise "Must have active connection to service" unless client
267
+ end
268
+
269
+ ##
270
+ # @private Raise an error unless an active connection to the service
271
+ # is available.
272
+ def ensure_service!
273
+ raise "Must have active connection to service" unless service
274
+ end
275
+
276
+ ##
277
+ # @private The Service object.
278
+ def service
279
+ ensure_client!
280
+ client.service
281
+ end
282
+ end
283
+ end
284
+ end
285
+ end
@@ -0,0 +1,145 @@
1
+ # Copyright 2022 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
+ # # AggregateQuerySnapshot
21
+ #
22
+ # An aggregate query snapshot object is an immutable representation for
23
+ # an aggregate query result.
24
+ #
25
+ # @example
26
+ # require "google/cloud/firestore"
27
+ #
28
+ # firestore = Google::Cloud::Firestore.new
29
+ #
30
+ # query = firestore.col "cities"
31
+ #
32
+ # # Create an aggregate query
33
+ # aggregate_query = query.aggregate_query
34
+ # .add_count
35
+ #
36
+ # aggregate_query.get do |aggregate_snapshot|
37
+ # puts aggregate_snapshot.get
38
+ # end
39
+ # @return [Integer] The aggregate value.
40
+ #
41
+ # @example Alias an aggregate query
42
+ # require "google/cloud/firestore"
43
+ #
44
+ # firestore = Google::Cloud::Firestore.new
45
+ #
46
+ # query = firestore.col "cities"
47
+ #
48
+ # # Create an aggregate query
49
+ # aggregate_query = query.aggregate_query
50
+ # .add_count aggregate_alias: 'total'
51
+ #
52
+ # aggregate_query.get do |aggregate_snapshot|
53
+ # puts aggregate_snapshot.get('total')
54
+ # end
55
+ class AggregateQuerySnapshot
56
+ ##
57
+ # @private Object of type [Hash{String => Object}]
58
+ #
59
+ # String can have the following values:
60
+ # - an aggregate literal "sum", "avg", or "count"
61
+ # - a custom aggregate alias
62
+ # Object can have the following types:
63
+ # - Integer
64
+ # - Float
65
+ # - nil
66
+ # - NaN
67
+ attr_reader :aggregate_fields
68
+
69
+ ##
70
+ # Retrieves the aggregate data.
71
+ #
72
+ # @param aggregate_alias [String] The alias used to access
73
+ # the aggregate value. For an AggregateQuery with a
74
+ # single aggregate field, this parameter can be omitted.
75
+ #
76
+ # @return [Integer, Float, nil, NaN] The aggregate value.
77
+ # Returns `nil` if the aggregate_alias does not exist.
78
+ # Returns `NaN` if the aggregate field contains one or more NaN values.
79
+ #
80
+ # @example
81
+ # require "google/cloud/firestore"
82
+ #
83
+ # firestore = Google::Cloud::Firestore.new
84
+ #
85
+ # query = firestore.col "cities"
86
+ #
87
+ # # Create an aggregate query
88
+ # aggregate_query = query.aggregate_query
89
+ # .add_count
90
+ #
91
+ # aggregate_query.get do |aggregate_snapshot|
92
+ # puts aggregate_snapshot.get
93
+ # end
94
+ # @return [Integer] The aggregate value.
95
+ #
96
+ # @example Alias an aggregate query
97
+ # require "google/cloud/firestore"
98
+ #
99
+ # firestore = Google::Cloud::Firestore.new
100
+ #
101
+ # query = firestore.col "cities"
102
+ #
103
+ # # Create an aggregate query
104
+ # aggregate_query = query.aggregate_query
105
+ # .add_count aggregate_alias: 'total'
106
+ #
107
+ # aggregate_query.get do |aggregate_snapshot|
108
+ # puts aggregate_snapshot.get('total')
109
+ # end
110
+ def get aggregate_alias = nil
111
+ if @aggregate_fields.count > 1 && aggregate_alias.nil?
112
+ raise ArgumentError, "Required param aggregate_alias for AggregateQuery with multiple aggregate fields"
113
+ end
114
+ aggregate_alias ||= @aggregate_fields.keys.first
115
+ @aggregate_fields[aggregate_alias]
116
+ end
117
+
118
+ ##
119
+ # @private New AggregateQuerySnapshot from a
120
+ # Google::Cloud::Firestore::V1::RunAggregationQueryResponse object.
121
+ def self.from_run_aggregate_query_response response
122
+ # rubocop:disable Style/MapToHash
123
+ aggregate_fields = response
124
+ .result
125
+ .aggregate_fields
126
+ .map do |aggregate_alias, value| # convert from protobuf to ruby map
127
+ if value.has_integer_value?
128
+ [aggregate_alias, value.integer_value]
129
+ elsif value.has_double_value?
130
+ [aggregate_alias, value.double_value]
131
+ elsif value.has_null_value?
132
+ [aggregate_alias, nil]
133
+ end
134
+ end
135
+ .to_h
136
+ # rubocop:enable Style/MapToHash
137
+
138
+ new.tap do |s|
139
+ s.instance_variable_set :@aggregate_fields, aggregate_fields
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,73 @@
1
+ # Copyright 2023 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
+ #
21
+ # @private Accumulate write operations to be sent in a batch. Use this for higher
22
+ # volumes (e.g., via `BulkWriter`) and when the order of operations
23
+ # within a given batch is unimportant.
24
+ #
25
+ # Because the order in which individual write operations are applied to the database
26
+ # is not guaranteed, `batch_write` RPCs can never contain multiple operations
27
+ # to the same document. In practice, the BulkWriter class handle this case.
28
+ #
29
+ class BulkCommitBatch
30
+ attr_reader :operations
31
+
32
+ ##
33
+ # Initialize the object
34
+ def initialize service, operations
35
+ @service = service
36
+ @operations = operations
37
+ end
38
+
39
+ ##
40
+ # Updates the operation based on the result received from the API request.
41
+ #
42
+ # @param [Google::Cloud::Firestore::V1::BatchWriteResponse] responses
43
+ #
44
+ # @return [nil]
45
+ #
46
+ def parse_results responses
47
+ @operations.zip responses.write_results, responses.status do |operation, write_result, status|
48
+ begin
49
+ status&.code&.zero? ? operation.on_success(write_result) : operation.on_failure(status)
50
+ rescue StandardError
51
+ # TODO: Log the error while parsing response
52
+ end
53
+ end
54
+ end
55
+
56
+ ##
57
+ # Makes the BatchWrite API request with all the operations in the batch and
58
+ # parses the results for each operation.
59
+ #
60
+ # @return [nil]
61
+ #
62
+ def commit
63
+ begin
64
+ responses = @service.batch_write @operations.map(&:write)
65
+ parse_results responses
66
+ rescue StandardError => e
67
+ raise BulkCommitBatchError, e
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end