@naturalcycles/datastore-lib
Version:
Opinionated library to work with Google Datastore, implements CommonDB
64 lines (63 loc) • 2.28 kB
JavaScript
import { PropertyFilter } from '@google-cloud/datastore';
import { _round } from '@naturalcycles/js-lib';
const FNAME_MAP = {
id: '__key__',
};
// export type Operator = '=' | '<' | '>' | '<=' | '>=' | 'HAS_ANCESTOR' | '!=' | 'IN' | 'NOT_IN'
const OP_MAP = {
'==': '=',
in: 'IN',
'not-in': 'NOT_IN',
};
export function dbQueryToDatastoreQuery(dbQuery, emptyQuery) {
let q = emptyQuery;
// filter
for (const f of dbQuery._filters) {
// keeping "previous syntax" commented out
// (q, f) => q.filter(f.name as string, OP_MAP[f.op] || (f.op as any), f.val),
// Datastore doesn't allow `undefined` as filter value.
// We don't want to throw on it, so instead we'll replace it with valid value of `null`.
// `a > null` will return anything that's indexed
// `a < null` should return nothing
// `a == null` will return just that - rows with null values
let { op, val } = f;
if (val === undefined)
val = null;
q = q.filter(new PropertyFilter(f.name, OP_MAP[op] || op, val));
}
// limit
q = q.limit(dbQuery._limitValue || 0);
// order
for (const ord of dbQuery._orders) {
q = q.order(ord.name, { descending: ord.descending });
}
// select
if (dbQuery._selectedFieldNames) {
const fields = dbQuery._selectedFieldNames.map(f => FNAME_MAP[f] || f);
// Datastore requires you to specify at least one column, so if empty array is passed - it'll include __key__ at least
if (!fields.length) {
fields.push('__key__');
}
q = q.select(fields);
}
// cursor
if (dbQuery._startCursor) {
q = q.start(dbQuery._startCursor);
}
if (dbQuery._endCursor) {
q = q.end(dbQuery._endCursor);
}
return q;
}
export function getRunQueryOptions(opt) {
if (!opt.readAt)
return {};
// Datastore expects UnixTimestamp in milliseconds
// Datastore requires the timestamp to be rounded to the whole minutes
let readTime = _round(opt.readAt, 60) * 1000;
if (readTime >= Date.now() - 1000) {
// To avoid the error of: The requested 'read_time' cannot be in the future
readTime -= 60_000;
}
return { readTime };
}