google-cloud-datastore 2.3.1 → 2.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c300ee184929b5e46058e32af1e18a2e0e786e3eb17b32d24a265713e442b75d
4
- data.tar.gz: 06752add810608b745cc157a60fcfc23aa77ab54a7395f54e8f8b2d3867fc882
3
+ metadata.gz: c5cb153ea77e6581236392f42ec5755cde46733fc2331d6c6b7f204e171c4006
4
+ data.tar.gz: 57e1bde4b98c1f21b7d65d56255d66b79ab19c7d0a62d03d67fdbc90027fe1ca
5
5
  SHA512:
6
- metadata.gz: aa87df55a375dba1110cd28463a59f0c81e81cfa4aa513edeb380302f63e6e4610a1e5064a47af57753aa4e31c21c092276cbbf92325a6a55b9e3cffb7cbbf35
7
- data.tar.gz: f39b9d73f4c149cf633b376d10aa811b7f3e8a607e294753e0b796319312082771a112d049c90d548fd80c8024b7b4b18fa11940a88fe07a62ee8e16b7b61d3f
6
+ metadata.gz: 950fa042833ec644777f8b2e89ed0078f4c4629f4f32d6833b6de20d7f4f09a4563c96fbb9515a0eb6e3d76ace6d610e63178033a6d6318a0b2b897b91ccfb4e
7
+ data.tar.gz: 4c6757326810a722fc9c2543bcbb0135b15ad698cd5b9b5bfdfe33ae4f84bf8e9df437d8838784f0a71c3debf7c51d8a6be70ed671efc9382cefddd10ec2c672
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Release History
2
2
 
3
+ ### 2.4.0 (2023-02-02)
4
+
5
+ #### Features
6
+
7
+ * Support query count for Datastore ([#20039](https://github.com/googleapis/google-cloud-ruby/issues/20039))
8
+
3
9
  ### 2.3.1 (2022-12-14)
4
10
 
5
11
  #### Bug Fixes
@@ -0,0 +1,139 @@
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
+ require "google/cloud/datastore/v1"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Datastore
21
+ ##
22
+ # # AggregateQuery
23
+ #
24
+ # An aggregate query can be used to fetch aggregate values (ex: count) for a query
25
+ #
26
+ # @example
27
+ # require "google/cloud/datastore"
28
+ #
29
+ # datastore = Google::Cloud::Datastore.new
30
+ #
31
+ # query = Google::Cloud::Datastore::Query.new
32
+ # query.kind("Task")
33
+ # .where("done", "=", false)
34
+ #
35
+ # Create an aggregate query
36
+ # aggregate_query = query.aggregate_query
37
+ # .add_count
38
+ #
39
+ # aggregate_query_results = dataset.run_aggregation aggregate_query
40
+ # puts aggregate_query_results.get
41
+ #
42
+ # @example Alias an aggregate query
43
+ # require "google/cloud/datastore"
44
+ #
45
+ # datastore = Google::Cloud::Datastore.new
46
+ #
47
+ # query = Google::Cloud::Datastore::Query.new
48
+ # query.kind("Task")
49
+ # .where("done", "=", false)
50
+ #
51
+ # Create an aggregate query
52
+ # aggregate_query = query.aggregate_query
53
+ # .add_count aggregate_alias: 'total'
54
+ #
55
+ # aggregate_query_results = dataset.run_aggregation aggregate_query
56
+ # puts aggregate_query_results.get('total')
57
+ #
58
+ class AggregateQuery
59
+ ##
60
+ # @private The Google::Cloud::Datastore::V1::Query object.
61
+ attr_reader :query
62
+
63
+ ##
64
+ # @private Array of Google::Cloud::Datastore::V1::AggregationQuery::Aggregation objects
65
+ attr_reader :aggregates
66
+
67
+ ##
68
+ # @private Creates a new AggregateQuery
69
+ def initialize query
70
+ @query = query
71
+ @aggregates = []
72
+ end
73
+
74
+ ##
75
+ # Adds a count aggregate.
76
+ #
77
+ # @param aggregate_alias [String] Alias to refer to the aggregate. Optional
78
+ #
79
+ # @return [AggregateQuery] The modified aggregate query object with the added count aggregate.
80
+ #
81
+ # @example
82
+ # require "google/cloud/datastore"
83
+ #
84
+ # datastore = Google::Cloud::Datastore.new
85
+ #
86
+ # query = Google::Cloud::Datastore::Query.new
87
+ # query.kind("Task")
88
+ # .where("done", "=", false)
89
+ #
90
+ # Create an aggregate query
91
+ # aggregate_query = query.aggregate_query
92
+ # .add_count
93
+ #
94
+ # aggregate_query_results = dataset.run_aggregation aggregate_query
95
+ # puts aggregate_query_results.get
96
+ #
97
+ # @example Alias an aggregate query
98
+ # require "google/cloud/datastore"
99
+ #
100
+ # datastore = Google::Cloud::Datastore.new
101
+ #
102
+ # query = Google::Cloud::Datastore::Query.new
103
+ # query.kind("Task")
104
+ # .where("done", "=", false)
105
+ #
106
+ # Create an aggregate query
107
+ # aggregate_query = query.aggregate_query
108
+ # .add_count aggregate_alias: 'total'
109
+ #
110
+ # aggregate_query_results = dataset.run_aggregation aggregate_query
111
+ # puts aggregate_query_results.get('total')
112
+ #
113
+ def add_count aggregate_alias: nil
114
+ aggregate_alias ||= ALIASES[:count]
115
+ aggregates << Google::Cloud::Datastore::V1::AggregationQuery::Aggregation.new(
116
+ count: Google::Cloud::Datastore::V1::AggregationQuery::Aggregation::Count.new,
117
+ alias: aggregate_alias
118
+ )
119
+
120
+ self
121
+ end
122
+
123
+ # @private
124
+ def to_grpc
125
+ Google::Cloud::Datastore::V1::AggregationQuery.new(
126
+ nested_query: query,
127
+ aggregations: aggregates
128
+ )
129
+ end
130
+
131
+ ##
132
+ # @private
133
+ ALIASES = {
134
+ count: "count"
135
+ }.freeze
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,115 @@
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
+ module Google
16
+ module Cloud
17
+ module Datastore
18
+ class Dataset
19
+ ##
20
+ # # AggregateQueryResults
21
+ #
22
+ # An AggregateQueryResult object is a representation for
23
+ # a result of an AggregateQuery or a GqlQuery.
24
+ #
25
+ # @example
26
+ # require "google/cloud/datastore"
27
+ #
28
+ # datastore = Google::Cloud::Datastore.new
29
+ #
30
+ # query = Google::Cloud::Datastore::Query.new
31
+ # query.kind("Task")
32
+ # .where("done", "=", false)
33
+ #
34
+ # Create an aggregate query
35
+ # aggregate_query = query.aggregate_query
36
+ # .add_count
37
+ #
38
+ # aggregate_query_results = dataset.run_aggregation aggregate_query
39
+ # puts aggregate_query_results.get
40
+ #
41
+ class AggregateQueryResults
42
+ ##
43
+ # Read timestamp the query was done on the database at.
44
+ #
45
+ # @return Google::Protobuf::Timestamp
46
+ attr_reader :read_time
47
+
48
+ ##
49
+ # Retrieves the aggregate data.
50
+ #
51
+ # @param aggregate_alias [String] The alias used to access
52
+ # the aggregate value. For an AggregateQuery with a
53
+ # single aggregate field, this parameter can be omitted.
54
+ #
55
+ # @return [Integer] The aggregate value.
56
+ #
57
+ # @example
58
+ # require "google/cloud/datastore"
59
+ #
60
+ # datastore = Google::Cloud::Datastore.new
61
+ #
62
+ # query = Google::Cloud::Datastore::Query.new
63
+ # query.kind("Task")
64
+ # .where("done", "=", false)
65
+ #
66
+ # Create an aggregate query
67
+ # aggregate_query = query.aggregate_query
68
+ # .add_count
69
+ #
70
+ # aggregate_query_results = dataset.run_aggregation aggregate_query
71
+ # puts aggregate_query_results.get
72
+ #
73
+ # @example Alias an aggregate query
74
+ # require "google/cloud/datastore"
75
+ #
76
+ # datastore = Google::Cloud::Datastore.new
77
+ #
78
+ # query = Google::Cloud::Datastore::Query.new
79
+ # query.kind("Task")
80
+ # .where("done", "=", false)
81
+ #
82
+ # Create an aggregate query
83
+ # aggregate_query = query.aggregate_query
84
+ # .add_count aggregate_alias: 'total'
85
+ #
86
+ # aggregate_query_results = dataset.run_aggregation aggregate_query
87
+ # puts aggregate_query_results.get('total')
88
+ def get aggregate_alias = nil
89
+ if @aggregate_fields.count > 1 && aggregate_alias.nil?
90
+ raise ArgumentError, "Required param aggregate_alias for AggregateQuery with multiple aggregate fields"
91
+ end
92
+ aggregate_alias ||= @aggregate_fields.keys.first
93
+ @aggregate_fields[aggregate_alias]
94
+ end
95
+
96
+ ##
97
+ # @private New AggregateQueryResults from a
98
+ # Google::Cloud::Datastore::V1::RunAggregationQueryResponse object.
99
+ def self.from_grpc aggregate_query_response
100
+ aggregate_fields = aggregate_query_response
101
+ .batch
102
+ .aggregation_results[0]
103
+ .aggregate_properties
104
+ .to_h
105
+ .transform_values { |v| v[:integer_value] }
106
+ new.tap do |s|
107
+ s.instance_variable_set :@aggregate_fields, aggregate_fields
108
+ s.instance_variable_set :@read_time, aggregate_query_response.batch.read_time
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -24,6 +24,7 @@ require "google/cloud/datastore/gql_query"
24
24
  require "google/cloud/datastore/cursor"
25
25
  require "google/cloud/datastore/dataset/lookup_results"
26
26
  require "google/cloud/datastore/dataset/query_results"
27
+ require "google/cloud/datastore/dataset/aggregate_query_results"
27
28
  require "google/cloud/datastore/transaction"
28
29
  require "google/cloud/datastore/read_only_transaction"
29
30
 
@@ -453,6 +454,88 @@ module Google
453
454
  end
454
455
  alias run_query run
455
456
 
457
+ ##
458
+ # Retrieve aggregate results specified by an AggregateQuery.
459
+ #
460
+ # @param [AggregateQuery, GqlQuery] query The object with the aggregate criteria.
461
+ # @param [String] namespace The namespace the query is to run within.
462
+ # @param [Symbol] consistency The non-transactional read consistency to
463
+ # use. Cannot be set to `:strong` for global queries. Accepted values
464
+ # are `:eventual` and `:strong`.
465
+ #
466
+ # The default consistency depends on the type of query used. See
467
+ # [Eventual Consistency in Google Cloud
468
+ # Datastore](https://cloud.google.com/datastore/docs/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore/#h.tf76fya5nqk8)
469
+ # for more information.
470
+ #
471
+ # @return [Google::Cloud::Datastore::Dataset::AggregateQueryResults]
472
+ #
473
+ # @example
474
+ # require "google/cloud/datastore"
475
+ #
476
+ # datastore = Google::Cloud::Datastore.new
477
+ #
478
+ # query = datastore.query("Task")
479
+ # .where("done", "=", false)
480
+ #
481
+ # aggregate_query = query.aggregate_query
482
+ #
483
+ # res = datastore.run_aggregation aggregate_query
484
+ #
485
+ # @example Run an aggregate ancestor query with eventual consistency:
486
+ # require "google/cloud/datastore"
487
+ #
488
+ # datastore = Google::Cloud::Datastore.new
489
+ #
490
+ # task_list_key = datastore.key "TaskList", "default"
491
+ # query = datastore.query.kind("Task")
492
+ # .ancestor(task_list_key)
493
+ #
494
+ # aggregate_query = query.aggregate_query
495
+ #
496
+ # res = datastore.run_aggregation aggregate_query, consistency: :eventual
497
+ #
498
+ # @example Run the aggregate query within a namespace with the `namespace` option:
499
+ # require "google/cloud/datastore"
500
+ #
501
+ # datastore = Google::Cloud::Datastore.new
502
+ #
503
+ # query = datastore.query("Task")
504
+ # .where("done", "=", false)
505
+ #
506
+ # aggregate_query = query.aggregate_query
507
+ #
508
+ # res = datastore.run_aggregation aggregate_query, namespace: "example-ns"
509
+ #
510
+ # @example Run the aggregate query with a GQL string.
511
+ # require "google/cloud/datastore"
512
+ #
513
+ # datastore = Google::Cloud::Datastore.new
514
+ #
515
+ # gql_query = datastore.gql "SELECT COUNT(*) FROM Task WHERE done = @done",
516
+ # done: false
517
+ # res = datastore.run_aggregation gql_query
518
+ #
519
+ # @example Run the aggregate GQL query within a namespace with `namespace` option:
520
+ # require "google/cloud/datastore"
521
+ #
522
+ # datastore = Google::Cloud::Datastore.new
523
+ #
524
+ # gql_query = datastore.gql "SELECT COUNT(*) FROM Task WHERE done = @done",
525
+ # done: false
526
+ # res = datastore.run_aggregation gql_query, namespace: "example-ns"
527
+ #
528
+ def run_aggregation aggregate_query, namespace: nil, consistency: nil
529
+ ensure_service!
530
+ unless aggregate_query.is_a?(AggregateQuery) || aggregate_query.is_a?(GqlQuery)
531
+ raise ArgumentError, "Cannot run a #{aggregate_query.class} object."
532
+ end
533
+ check_consistency! consistency
534
+ aggregate_query_res = service.run_aggregation_query aggregate_query.to_grpc, namespace,
535
+ consistency: consistency
536
+ AggregateQueryResults.from_grpc aggregate_query_res
537
+ end
538
+
456
539
  ##
457
540
  # Creates a Datastore Transaction.
458
541
  #
@@ -15,6 +15,7 @@
15
15
 
16
16
  require "google/cloud/datastore/entity"
17
17
  require "google/cloud/datastore/key"
18
+ require "google/cloud/datastore/aggregate_query"
18
19
 
19
20
  module Google
20
21
  module Cloud
@@ -425,6 +426,27 @@ module Google
425
426
  end
426
427
  alias distinct_on group_by
427
428
 
429
+ ##
430
+ # Creates an AggregateQuery object for the query.
431
+ #
432
+ # @return [AggregateQuery] New empty aggregate query.
433
+ #
434
+ # @example
435
+ # require "google/cloud/datastore"
436
+ #
437
+ # datastore = Google::Cloud::Datastore.new
438
+ #
439
+ # query = Google::Cloud::Datastore::Query.new
440
+ # query.kind("Task")
441
+ # .where("done", "=", false)
442
+ #
443
+ # Create an aggregate query
444
+ # aggregate_query = query.aggregate_query
445
+ #
446
+ def aggregate_query
447
+ AggregateQuery.new @grpc
448
+ end
449
+
428
450
  # @private
429
451
  def to_grpc
430
452
  @grpc
@@ -157,6 +157,37 @@ module Google
157
157
  end
158
158
  alias run_query run
159
159
 
160
+ ##
161
+ # Retrieve aggregate query results specified by an AggregateQuery. The query is run within the
162
+ # transaction.
163
+ #
164
+ # @param [AggregateQuery, GqlQuery] query The Query object with the search criteria.
165
+ # @param [String] namespace The namespace the query is to run within.
166
+ #
167
+ # @return [Google::Cloud::Datastore::Dataset::AggregateQueryResults]
168
+ #
169
+ # @example
170
+ # require "google/cloud/datastore"
171
+ #
172
+ # datastore = Google::Cloud::Datastore.new
173
+ #
174
+ # datastore.read_only_transaction do |tx|
175
+ # query = tx.query("Task")
176
+ # .where("done", "=", false)
177
+ # aggregate_query = query.aggregate_query
178
+ # .add_count
179
+ # res = tx.run_aggregation aggregate_query
180
+ # end
181
+ #
182
+ def run_aggregation aggregate_query, namespace: nil
183
+ ensure_service!
184
+ unless aggregate_query.is_a?(AggregateQuery) || aggregate_query.is_a?(GqlQuery)
185
+ raise ArgumentError, "Cannot run a #{aggregate_query.class} object."
186
+ end
187
+ aggregate_query_results = service.run_aggregation_query aggregate_query.to_grpc, namespace, transaction: @id
188
+ Dataset::AggregateQueryResults.from_grpc aggregate_query_results
189
+ end
190
+
160
191
  ##
161
192
  # Begins a transaction.
162
193
  # This method is run when a new ReadOnlyTransaction is created.
@@ -88,6 +88,27 @@ module Google
88
88
  gql_query: gql_query
89
89
  end
90
90
 
91
+ ## Query for aggregates
92
+ def run_aggregation_query query, namespace = nil, consistency: nil, transaction: nil
93
+ gql_query = nil
94
+ if query.is_a? Google::Cloud::Datastore::V1::GqlQuery
95
+ gql_query = query
96
+ query = nil
97
+ end
98
+ read_options = generate_read_options consistency, transaction
99
+ if namespace
100
+ partition_id = Google::Cloud::Datastore::V1::PartitionId.new(
101
+ namespace_id: namespace
102
+ )
103
+ end
104
+
105
+ service.run_aggregation_query project_id: project,
106
+ partition_id: partition_id,
107
+ read_options: read_options,
108
+ aggregation_query: query,
109
+ gql_query: gql_query
110
+ end
111
+
91
112
  ##
92
113
  # Begin a new transaction.
93
114
  def begin_transaction read_only: nil, previous_transaction: nil
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Datastore
19
- VERSION = "2.3.1".freeze
19
+ VERSION = "2.4.0".freeze
20
20
  end
21
21
  end
22
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-datastore
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Moore
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-12-14 00:00:00.000000000 Z
12
+ date: 2023-02-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-cloud-core
@@ -199,11 +199,13 @@ files:
199
199
  - TROUBLESHOOTING.md
200
200
  - lib/google-cloud-datastore.rb
201
201
  - lib/google/cloud/datastore.rb
202
+ - lib/google/cloud/datastore/aggregate_query.rb
202
203
  - lib/google/cloud/datastore/commit.rb
203
204
  - lib/google/cloud/datastore/convert.rb
204
205
  - lib/google/cloud/datastore/credentials.rb
205
206
  - lib/google/cloud/datastore/cursor.rb
206
207
  - lib/google/cloud/datastore/dataset.rb
208
+ - lib/google/cloud/datastore/dataset/aggregate_query_results.rb
207
209
  - lib/google/cloud/datastore/dataset/lookup_results.rb
208
210
  - lib/google/cloud/datastore/dataset/query_results.rb
209
211
  - lib/google/cloud/datastore/entity.rb
@@ -235,7 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
237
  - !ruby/object:Gem::Version
236
238
  version: '0'
237
239
  requirements: []
238
- rubygems_version: 3.3.14
240
+ rubygems_version: 3.4.2
239
241
  signing_key:
240
242
  specification_version: 4
241
243
  summary: API Client library for Google Cloud Datastore