UNPKG

14.9 kBJavaScriptView Raw
1"use strict";
2/*!
3 * Copyright 2014 Google LLC.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.Query = void 0;
19const arrify = require("arrify");
20/**
21 * Build a Query object.
22 *
23 * **Queries are built with {module:datastore#createQuery} and
24 * {@link Transaction#createQuery}.**
25 *
26 * @see [Datastore Queries]{@link http://goo.gl/Cag0r6}
27 *
28 * @class
29 * @param {Datastore|Transaction} scope The parent scope the query was created
30 * from.
31 * @param {string} [namespace] Namespace to query entities from.
32 * @param {string[]} kinds Kind to query.
33 *
34 * @example
35 * const {Datastore} = require('@google-cloud/datastore');
36 * const datastore = new Datastore();
37 * const query = datastore.createQuery('AnimalNamespace', 'Lion');
38 */
39class Query {
40 constructor(scope, namespaceOrKinds, kinds) {
41 let namespace = namespaceOrKinds;
42 if (!kinds) {
43 kinds = namespaceOrKinds;
44 namespace = null;
45 }
46 /**
47 * @name Query#scope
48 * @type {Datastore|Transaction}
49 */
50 this.scope = scope;
51 /**
52 * @name Query#namespace
53 * @type {?string}
54 */
55 this.namespace = namespace || null;
56 /**
57 * @name Query#kinds
58 * @type {string}
59 */
60 this.kinds = kinds;
61 /**
62 * @name Query#filters
63 * @type {array}
64 */
65 this.filters = [];
66 /**
67 * @name Query#orders
68 * @type {array}
69 */
70 this.orders = [];
71 /**
72 * @name Query#groupByVal
73 * @type {array}
74 */
75 this.groupByVal = [];
76 /**
77 * @name Query#selectVal
78 * @type {array}
79 */
80 this.selectVal = [];
81 // pagination
82 /**
83 * @name Query#startVal
84 * @type {?number}
85 */
86 this.startVal = null;
87 /**
88 * @name Query#endVal
89 * @type {?number}
90 */
91 this.endVal = null;
92 /**
93 * @name Query#limitVal
94 * @type {number}
95 */
96 this.limitVal = -1;
97 /**
98 * @name Query#offsetVal
99 * @type {number}
100 */
101 this.offsetVal = -1;
102 }
103 /**
104 * Datastore allows querying on properties. Supported comparison operators
105 * are `=`, `<`, `>`, `<=`, and `>=`. "Not equal" and `IN` operators are
106 * currently not supported.
107 *
108 * *To filter by ancestors, see {module:datastore/query#hasAncestor}.*
109 *
110 * @see [Datastore Filters]{@link https://cloud.google.com/datastore/docs/concepts/queries#datastore-property-filter-nodejs}
111 *
112 * @param {string} property The field name.
113 * @param {string} [operator="="] Operator (=, <, >, <=, >=).
114 * @param {*} value Value to compare property to.
115 * @returns {Query}
116 *
117 * @example
118 * const {Datastore} = require('@google-cloud/datastore');
119 * const datastore = new Datastore();
120 * const query = datastore.createQuery('Company');
121 *
122 * //-
123 * // List all companies that are located in California.
124 * //-
125 * const caliQuery = query.filter('state', 'CA');
126 *
127 * //-
128 * // List all companies named Google that have less than 400 employees.
129 * //-
130 * const companyQuery = query
131 * .filter('name', 'Google')
132 * .filter('size', '<', 400);
133 *
134 * //-
135 * // To filter by key, use `__key__` for the property name. Filter on keys
136 * // stored as properties is not currently supported.
137 * //-
138 * const key = datastore.key(['Company', 'Google']);
139 * const keyQuery = query.filter('__key__', key);
140 */
141 filter(property, operatorOrValue, value) {
142 let operator = operatorOrValue;
143 if (arguments.length === 2) {
144 value = operatorOrValue;
145 operator = '=';
146 }
147 this.filters.push({
148 name: property.trim(),
149 op: operator.trim(),
150 val: value,
151 });
152 return this;
153 }
154 /**
155 * Filter a query by ancestors.
156 *
157 * @see [Datastore Ancestor Filters]{@link https://cloud.google.com/datastore/docs/concepts/queries#datastore-ancestor-query-nodejs}
158 *
159 * @param {Key} key Key object to filter by.
160 * @returns {Query}
161 *
162 * @example
163 * const {Datastore} = require('@google-cloud/datastore');
164 * const datastore = new Datastore();
165 * const query = datastore.createQuery('MyKind');
166 * const ancestoryQuery = query.hasAncestor(datastore.key(['Parent', 123]));
167 */
168 hasAncestor(key) {
169 this.filters.push({ name: '__key__', op: 'HAS_ANCESTOR', val: key });
170 return this;
171 }
172 /**
173 * Sort the results by a property name in ascending or descending order. By
174 * default, an ascending sort order will be used.
175 *
176 * @see [Datastore Sort Orders]{@link https://cloud.google.com/datastore/docs/concepts/queries#datastore-ascending-sort-nodejs}
177 *
178 * @param {string} property The property to order by.
179 * @param {object} [options] Options object.
180 * @param {boolean} [options.descending=false] Sort the results by a property
181 * name in descending order.
182 * @returns {Query}
183 *
184 * @example
185 * const {Datastore} = require('@google-cloud/datastore');
186 * const datastore = new Datastore();
187 * const companyQuery = datastore.createQuery('Company');
188 *
189 * // Sort by size ascendingly.
190 * const companiesAscending = companyQuery.order('size');
191 *
192 * // Sort by size descendingly.
193 * const companiesDescending = companyQuery.order('size', {
194 * descending: true
195 * });
196 */
197 order(property, options) {
198 const sign = options && options.descending ? '-' : '+';
199 this.orders.push({ name: property, sign });
200 return this;
201 }
202 /**
203 * Group query results by a list of properties.
204 *
205 * @param {array} properties Properties to group by.
206 * @returns {Query}
207 *
208 * @example
209 * const {Datastore} = require('@google-cloud/datastore');
210 * const datastore = new Datastore();
211 * const companyQuery = datastore.createQuery('Company');
212 * const groupedQuery = companyQuery.groupBy(['name', 'size']);
213 */
214 groupBy(fieldNames) {
215 this.groupByVal = arrify(fieldNames);
216 return this;
217 }
218 /**
219 * Retrieve only select properties from the matched entities.
220 *
221 * Queries that select a subset of properties are called Projection Queries.
222 *
223 * @see [Projection Queries]{@link https://cloud.google.com/datastore/docs/concepts/projectionqueries}
224 *
225 * @param {string|string[]} fieldNames Properties to return from the matched
226 * entities.
227 * @returns {Query}
228 *
229 * @example
230 * const {Datastore} = require('@google-cloud/datastore');
231 * const datastore = new Datastore();
232 * const companyQuery = datastore.createQuery('Company');
233 *
234 * // Only retrieve the name property.
235 * const selectQuery = companyQuery.select('name');
236 *
237 * // Only retrieve the name and size properties.
238 * const selectQuery = companyQuery.select(['name', 'size']);
239 */
240 select(fieldNames) {
241 this.selectVal = arrify(fieldNames);
242 return this;
243 }
244 /**
245 * Set a starting cursor to a query.
246 *
247 * @see [Query Cursors]{@link https://cloud.google.com/datastore/docs/concepts/queries#cursors_limits_and_offsets}
248 *
249 * @param {string} cursorToken The starting cursor token.
250 * @returns {Query}
251 *
252 * @example
253 * const {Datastore} = require('@google-cloud/datastore');
254 * const datastore = new Datastore();
255 * const companyQuery = datastore.createQuery('Company');
256 *
257 * const cursorToken = 'X';
258 *
259 * // Retrieve results starting from cursorToken.
260 * const startQuery = companyQuery.start(cursorToken);
261 */
262 start(start) {
263 this.startVal = start;
264 return this;
265 }
266 /**
267 * Set an ending cursor to a query.
268 *
269 * @see [Query Cursors]{@link https://cloud.google.com/datastore/docs/concepts/queries#Datastore_Query_cursors}
270 *
271 * @param {string} cursorToken The ending cursor token.
272 * @returns {Query}
273 *
274 * @example
275 * const {Datastore} = require('@google-cloud/datastore');
276 * const datastore = new Datastore();
277 * const companyQuery = datastore.createQuery('Company');
278 *
279 * const cursorToken = 'X';
280 *
281 * // Retrieve results limited to the extent of cursorToken.
282 * const endQuery = companyQuery.end(cursorToken);
283 */
284 end(end) {
285 this.endVal = end;
286 return this;
287 }
288 /**
289 * Set a limit on a query.
290 *
291 * @see [Query Limits]{@link https://cloud.google.com/datastore/docs/concepts/queries#datastore-limit-nodejs}
292 *
293 * @param {number} n The number of results to limit the query to.
294 * @returns {Query}
295 *
296 * @example
297 * const {Datastore} = require('@google-cloud/datastore');
298 * const datastore = new Datastore();
299 * const companyQuery = datastore.createQuery('Company');
300 *
301 * // Limit the results to 10 entities.
302 * const limitQuery = companyQuery.limit(10);
303 */
304 limit(n) {
305 this.limitVal = n;
306 return this;
307 }
308 /**
309 * Set an offset on a query.
310 *
311 * @see [Query Offsets]{@link https://cloud.google.com/datastore/docs/concepts/queries#datastore-limit-nodejs}
312 *
313 * @param {number} n The offset to start from after the start cursor.
314 * @returns {Query}
315 *
316 * @example
317 * const {Datastore} = require('@google-cloud/datastore');
318 * const datastore = new Datastore();
319 * const companyQuery = datastore.createQuery('Company');
320 *
321 * // Start from the 101st result.
322 * const offsetQuery = companyQuery.offset(100);
323 */
324 offset(n) {
325 this.offsetVal = n;
326 return this;
327 }
328 /**
329 * Run the query.
330 *
331 * @param {object} [options] Optional configuration.
332 * @param {string} [options.consistency] Specify either `strong` or `eventual`.
333 * If not specified, default values are chosen by Datastore for the
334 * operation. Learn more about strong and eventual consistency
335 * [here](https://cloud.google.com/datastore/docs/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore).
336 * @param {object} [options.gaxOptions] Request configuration options, outlined
337 * here: https://googleapis.github.io/gax-nodejs/global.html#CallOptions.
338 * @param {boolean | IntegerTypeCastOptions} [options.wrapNumbers=false]
339 * Wrap values of integerValue type in {@link Datastore#Int} objects.
340 * If a `boolean`, this will wrap values in {@link Datastore#Int} objects.
341 * If an `object`, this will return a value returned by
342 * `wrapNumbers.integerTypeCastFunction`.
343 * Please see {@link IntegerTypeCastOptions} for options descriptions.
344 * @param {function} [callback] The callback function. If omitted, a readable
345 * stream instance is returned.
346 * @param {?error} callback.err An error returned while making this request
347 * @param {object[]} callback.entities A list of entities.
348 * @param {object} callback.info An object useful for pagination.
349 * @param {?string} callback.info.endCursor Use this in a follow-up query to
350 * begin from where these results ended.
351 * @param {string} callback.info.moreResults Datastore responds with one of:
352 *
353 * - {@link Datastore#MORE_RESULTS_AFTER_LIMIT}: There *may* be more
354 * results after the specified limit.
355 * - {@link Datastore#MORE_RESULTS_AFTER_CURSOR}: There *may* be more
356 * results after the specified end cursor.
357 * - {@link Datastore#NO_MORE_RESULTS}: There are no more results.
358 *
359 * @example
360 * const {Datastore} = require('@google-cloud/datastore');
361 * const datastore = new Datastore();
362 * const query = datastore.createQuery('Company');
363 *
364 * query.run((err, entities, info) => {
365 * // entities = An array of records.
366 *
367 * // Access the Key object for an entity.
368 * const firstEntityKey = entities[0][datastore.KEY];
369 * });
370 *
371 * //-
372 * // A keys-only query returns just the keys of the result entities instead
373 * of
374 * // the entities themselves, at lower latency and cost.
375 * //-
376 * query.select('__key__');
377 *
378 * query.run((err, entities) => {
379 * const keys = entities.map((entity) => {
380 * return entity[datastore.KEY];
381 * });
382 * });
383 *
384 * //-
385 * // If the callback is omitted, we'll return a Promise.
386 * //-
387 * query.run().then((data) => {
388 * const entities = data[0];
389 * });
390 */
391 run(optionsOrCallback, cb) {
392 const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {};
393 const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
394 const runQuery = this.scope.runQuery.bind(this.scope);
395 return runQuery(this, options, callback);
396 }
397 /**
398 * Run the query as a readable object stream.
399 *
400 * @method Query#runStream
401 * @param {object} [options] Optional configuration. See
402 * {@link Query#run} for a complete list of options.
403 * @returns {stream}
404 *
405 * @example
406 * const {Datastore} = require('@google-cloud/datastore');
407 * const datastore = new Datastore();
408 * const query = datastore.createQuery('Company');
409 *
410 * query.runStream()
411 * .on('error', console.error)
412 * .on('data', function (entity) {
413 * // Access the Key object for this entity.
414 * const key = entity[datastore.KEY];
415 * })
416 * .on('info', (info) => {})
417 * .on('end', () => {
418 * // All entities retrieved.
419 * });
420 *
421 * //-
422 * // If you anticipate many results, you can end a stream early to prevent
423 * // unnecessary processing and API requests.
424 * //-
425 * query.runStream()
426 * .on('data', function (entity) {
427 * this.end();
428 * });
429 */
430 runStream(options) {
431 return this.scope.runQueryStream(this, options);
432 }
433}
434exports.Query = Query;
435//# sourceMappingURL=query.js.map
\No newline at end of file