mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 11:17:08 +00:00
@@ -9,12 +9,76 @@ function fields (obj, keys) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** Perform a restrict (aka select) operation on the relation.
|
||||
*
|
||||
* Recognised queries are:
|
||||
*
|
||||
* - tstamp:i; tolerance:j
|
||||
* - pos:λ,φ; radius: ρ
|
||||
*
|
||||
* Defaults:
|
||||
*
|
||||
* - tolerance: 1000 (ms)
|
||||
* - radius: 1 (m)
|
||||
*
|
||||
* Queries are ANDed together.
|
||||
*/
|
||||
function restrict (q="") {
|
||||
let sql = [];
|
||||
|
||||
/* This takes in a string of the form:
|
||||
* "key0=value0;key1=value1;key2=value=2"
|
||||
* and returns an object like:
|
||||
* { key0: "value0", key1: "value1", key2: "value=2" }
|
||||
*/
|
||||
const constraints = Object.fromEntries(q.split(/\s*;\s*/).map(i => {
|
||||
const parts = i.split(/(\s*:\s*)/);
|
||||
return [parts[0], parts.slice(2).join("")]
|
||||
}));
|
||||
|
||||
// TODO Consider adding an event_tstamp field, or indexing meta->>tstamp
|
||||
if ("tstamp" in constraints) {
|
||||
const ts = new Date(constraints.tstamp);
|
||||
|
||||
if (isNaN(ts)) {
|
||||
throw new Error("Invalid query");
|
||||
}
|
||||
|
||||
const tolerance = constraints.tolerance ?? 1000;
|
||||
const ts0 = new Date(ts.valueOf()-Number(tolerance));
|
||||
const ts1 = new Date(ts.valueOf()+Number(tolerance));
|
||||
console.log(tolerance, ts, ts0, ts1);
|
||||
console.log(constraints);
|
||||
|
||||
if (!isNaN(ts0) && !isNaN(ts1)) {
|
||||
sql.push(`(meta->>'tstamp')::timestamptz BETWEEN '${ts0.toISOString()}' AND '${ts1.toISOString()}'`);
|
||||
} else {
|
||||
throw new Error("Invalid query");
|
||||
}
|
||||
}
|
||||
|
||||
if ("pos" in constraints) {
|
||||
const [ lon, lat ] = constraints.pos.split(",").map(i => Number(i));
|
||||
|
||||
if (isNaN(lon) || isNaN(lat)) {
|
||||
throw new Error("Invalid query");
|
||||
}
|
||||
|
||||
const radius = constraints.radius ?? 1;
|
||||
|
||||
sql.push(`ST_DistanceSphere(geometry, ST_Point(${lon}, ${lat}, 4326)) <= ${radius}`)
|
||||
}
|
||||
|
||||
return sql.length ? ("WHERE " + sql.join(" AND ")) : "";
|
||||
}
|
||||
|
||||
async function get (opts = {}) {
|
||||
const client = await pool.connect();
|
||||
|
||||
const text = `
|
||||
SELECT meta
|
||||
FROM real_time_inputs
|
||||
${restrict(opts.q)}
|
||||
ORDER BY tstamp DESC
|
||||
LIMIT $1
|
||||
OFFSET $2
|
||||
@@ -24,6 +88,7 @@ async function get (opts = {}) {
|
||||
|
||||
const res = await client.query(text, values);
|
||||
client.release();
|
||||
// TODO Must change this to use utils/project instead.
|
||||
return opts.fields
|
||||
? res.rows.map(r => fields(r.meta, opts.fields.split(/[;,\s]+/)))
|
||||
: res.rows.map(r => r.meta);
|
||||
|
||||
Reference in New Issue
Block a user