Skip to content

Commit 76adfc6

Browse files
danieljbrucetelpiriongcf-owl-bot[bot]ruyadornokolea2
authored
feat: Add the count aggregate function (#972)
* Files copied over * implementation of aggregate queries. * Checkout index.ts previous version * src seems to be error free * optional parameters * replace with recognized type * protos generated * old package.json * aggregation query request * Commit so I can revert * Revert "aggregation query request" This reverts commit 0f2bd32. * Revert "Revert "aggregation query request"" This reverts commit 1733072. * Added a parser * Comment out filters * Fixed parser * Add info * more tests, adding alias * use deep strict equal instead * Work on passing in buffered input. * Convert to buffer * Add alias * Add the aggregate function * change test descriptions * Add a unit test * Revert "Files copied over" This reverts commit fe55548. # Conflicts: # src/index.ts * Revert "protos generated" This reverts commit 1b21ec2. * Eliminate comments * Add new line * Change upTo * Change maximum name to upTo * upTo relabelled from maximum * remove import * ran the linter * improve code readability * move self equals this * change header * Revert "change header" This reverts commit b3ea976. * Add a header * change the unit test * Architecture changes * Getting closer * Add the right parsing * TODO message * Remove and add array over for aggregate fields * unit test and count function * fix unit test as result of new changes * linting fix * Added a test for encoding using a count function * lint fix * removed upTo * merge * undid local changes to package.json * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * Update src/aggregate.ts Co-authored-by: Ruy Adorno <[email protected]> * per reviewer * refactor and rename some methods * Add run method to aggregate query * test update and return value change * compare aggregate results * createAggregationQuery * linter and header fix * TODOs * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * Remove autogenerated comment * count aggregation with limit filter tests * lint fix * Commented functions and classes Co-authored-by: Eric Schmidt <[email protected]> Co-authored-by: Eric Schmidt <[email protected]> Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com> Co-authored-by: Ruy Adorno <[email protected]> Co-authored-by: Kristen O'Leary <[email protected]>
1 parent 6b2472b commit 76adfc6

File tree

11 files changed

+415
-30
lines changed

11 files changed

+415
-30
lines changed

protos/protos.d.ts

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protos/protos.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/aggregate.ts

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
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+
import {Query} from './index';
16+
import {RunQueryOptions, RunQueryResponse} from './query';
17+
import {RequestCallback} from './request';
18+
const AGGREGATE_QUERY = Symbol('AGGREGATE_QUERY');
19+
20+
/**
21+
* An AggregateQuery is a class that can be used to obtain results from an
22+
* aggregate query request.
23+
*
24+
* @see {@link https://cloud.google.com/datastore/docs/aggregation-queries| Aggregation queries Reference}
25+
*
26+
* @class
27+
*/
28+
class AggregateQuery {
29+
type = AGGREGATE_QUERY;
30+
aggregations: Array<AggregateField>;
31+
query: Query | undefined;
32+
33+
/**
34+
* Build an AggregateQuery object.
35+
*
36+
* @param {Query} query
37+
*/
38+
constructor(query: Query) {
39+
this.query = query;
40+
this.aggregations = [];
41+
}
42+
43+
/**
44+
* Add a `count` aggregate query to the list of aggregations.
45+
*
46+
* @param {string} alias
47+
* @returns {AggregateQuery}
48+
*/
49+
count(alias: string): AggregateQuery {
50+
this.aggregations.push(AggregateField.count().alias(alias));
51+
return this;
52+
}
53+
54+
/**
55+
* Add a custom aggregation to the list of aggregations.
56+
*
57+
* @param {AggregateField} aggregation
58+
* @returns {AggregateQuery}
59+
*/
60+
addAggregation(aggregation: AggregateField): AggregateQuery {
61+
this.aggregations.push(aggregation);
62+
return this;
63+
}
64+
65+
/**
66+
* Add a list of custom aggregations to the list of aggregations.
67+
*
68+
* @param {AggregateField[]} aggregation
69+
* @returns {AggregateQuery}
70+
*/
71+
addAggregations(aggregations: AggregateField[]): AggregateQuery {
72+
for (const aggregation of aggregations) {
73+
this.aggregations.push(aggregation);
74+
}
75+
return this;
76+
}
77+
78+
/**
79+
* Run the aggregation query and return the results.
80+
*
81+
* @param {RunQueryOptions | RequestCallback} [optionsOrCallback]
82+
* @param {function} cb The callback function.
83+
* @returns {void | Promise<RunQueryResponse>}
84+
*/
85+
run(
86+
optionsOrCallback?: RunQueryOptions | RequestCallback,
87+
cb?: RequestCallback
88+
): void | Promise<RunQueryResponse> {
89+
const options =
90+
typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
91+
const callback =
92+
typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!;
93+
const scope = this.query!.scope;
94+
const runAggregationQuery = scope!.runAggregationQuery.bind(scope);
95+
return runAggregationQuery(this, options, callback);
96+
}
97+
98+
/**
99+
* Get the proto for the list of aggregations.
100+
*
101+
*/
102+
// eslint-disable-next-line
103+
toProto(): any {
104+
return this.aggregations.map(aggregation => aggregation.toProto());
105+
}
106+
}
107+
108+
/**
109+
* An AggregateField is a class that contains data that defines an aggregation.
110+
*
111+
*/
112+
abstract class AggregateField {
113+
alias_?: string;
114+
115+
/**
116+
* Gets a copy of the Count aggregate field.
117+
*
118+
* @returns {Count}
119+
*/
120+
static count(): Count {
121+
return new Count();
122+
}
123+
124+
/**
125+
* Gets a copy of the Count aggregate field.
126+
*
127+
* @param {string} alias The label used in the results to describe this
128+
* aggregate field when a query is run.
129+
* @returns {AggregateField}
130+
*/
131+
alias(alias: string): AggregateField {
132+
this.alias_ = alias;
133+
return this;
134+
}
135+
136+
/**
137+
* Gets the proto for the aggregate field.
138+
*
139+
*/
140+
// eslint-disable-next-line
141+
abstract toProto(): any;
142+
}
143+
144+
/**
145+
* A Count is a class that contains data that defines a Count aggregation.
146+
*
147+
*/
148+
class Count extends AggregateField {
149+
// eslint-disable-next-line
150+
/**
151+
* Gets the proto for the count aggregate field.
152+
*
153+
*/
154+
toProto(): any {
155+
const count = Object.assign({});
156+
return Object.assign({count}, this.alias_ ? {alias: this.alias_} : null);
157+
}
158+
}
159+
160+
export {AggregateField, AggregateQuery, AGGREGATE_QUERY};

src/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import {
6464
import {Transaction} from './transaction';
6565
import {promisifyAll} from '@google-cloud/promisify';
6666
import {google} from '../protos/protos';
67+
import {AggregateQuery} from './aggregate';
6768

6869
const {grpc} = new GrpcClient();
6970

@@ -509,6 +510,15 @@ class Datastore extends DatastoreRequest {
509510
this.auth = new GoogleAuth(this.options);
510511
}
511512

513+
/**
514+
* Create an aggregation query from a Query.
515+
*
516+
* @param {Query} query A Query object.
517+
*/
518+
createAggregationQuery(query: Query): AggregateQuery {
519+
return new AggregateQuery(query);
520+
}
521+
512522
/**
513523
* Export entities from this project to a Google Cloud Storage bucket.
514524
*
@@ -1797,10 +1807,12 @@ class Datastore extends DatastoreRequest {
17971807
*/
17981808
promisifyAll(Datastore, {
17991809
exclude: [
1810+
'createAggregationQuery',
18001811
'double',
18011812
'isDouble',
18021813
'geoPoint',
18031814
'getProjectId',
1815+
'getSharedQueryOptions',
18041816
'isGeoPoint',
18051817
'index',
18061818
'int',

src/query.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {Entity} from './entity';
2121
import {Transaction} from './transaction';
2222
import {CallOptions} from 'google-gax';
2323
import {RunQueryStreamOptions} from '../src/request';
24+
import {AggregateField, AggregateQuery} from './aggregate';
2425

2526
export type Operator =
2627
| '='
@@ -572,6 +573,8 @@ export interface RunQueryCallback {
572573

573574
export type RunQueryResponse = [Entity[], RunQueryInfo];
574575

576+
export type RunAggregateQueryResponse = any;
577+
575578
export interface RunQueryInfo {
576579
endCursor?: string;
577580
moreResults?:

0 commit comments

Comments
 (0)