我正在尝试执行高级分析查询来驱动 Web 应用程序。我将 Hapi、Objection、Knex 和 Postgres 与 TimescaleDB 一起使用。对于典型的关系查询,这一切都运行良好。但是,我无法弄清楚如何执行这个涉及加入从 Postgres 生成的匿名表的聚合查询generate_series
。我不得不求助于编写原始 SQL,而不是 Objection/Knex 查询生成器。我正在使用一些 Postgres 的内置函数,以及time_bucket
来自 Timescale 的函数。time_bucket
本质上是根据参数中指定的间隔创建数据的汇总。查看此链接以获取有关我正在尝试执行Gap Filling的更多信息。
这是查询,它使用异议模型上的原始方法工作。我相信像这样进行字符串插值会导致潜在的 SQL 注入。但是,我希望将其转换为 Objection/Knex 使用的查询构建器方法,因此它更多的是 JavaScript,而不是 SQL,这将解决 SQL 注入问题。
let errorHistorgram = await Errors
.raw(`SELECT period AS daily, coalesce(count,0) AS count
FROM generate_series(date '${startTS}', date '${today}', interval '1d') AS period
LEFT JOIN (
SELECT time_bucket('1d',timestamp)::date AS date, count(timestamp)
FROM my_error_table
WHERE severity = 'HIGH'
AND timestamp >= '${startTS}' AND timestamp < '${today}'
AND device_id = ${deviceId}
GROUP BY date
) t ON t.date = period;`)
.debug();
我已经用 Objection/Knex 做了几次尝试。这是我制作此查询的最成功尝试。但是,我认为 where 子句不在正确的位置。
let errorHistorgram = await Errors
.query()
.select(raw(`time_bucket('1 day', timestamp) AS daily, count(timestamp)`))
.where('device_id', deviceId)
.andWhere('timestamp', '>', startTS)
.andWhere('severity', 'HIGH')
.leftJoin(`generate_series(date ${startTS}, date ${today}, interval 1d) AS series`, 'series.date', 'my_error_table.timestamp')
.debug();
使用.debug()
,我可以看到下面发布的查询输出。
select time_bucket('1 day', timestamp) AS daily, count(timestamp)
from my_error_table
left join "generate_series(date 2018-11-08T15:35:33"."050Z, date 2018-11-15T15:35:33"."133Z, interval 1d)" as "series"
on "series"."date" = my_error_table."timestamp"
where "device_id" = ? and "timestamp" > ? and "severity" = ?'
感谢您提供任何帮助,因为我没有使用 Objection 来执行此操作,并且找不到任何文档。
2018 年 11 月 15 日更新
我得到它来执行带有异议的查询。但是,我得到一个空数组作为结果。与我在上面制作的原始 SQL 查询不同(它确实给了我预期的结果),我只得到一个空数组作为查询生成器的输出。关于我做错了什么的任何想法。我试图将连接翻转为正确的连接,但没有运气。
let errorHistorgram = await Errors
.query()
.select(raw(`time_bucket('1 day', timestamp) AS daily, count(timestamp)`))
.where('device_id', deviceId)
.andWhere('timestamp', '>', startTS)
.andWhere('severity', 'HIGH')
.groupBy('timestamp')
.rightJoin(raw(`generate_series(date '${startTS}', date '${today}', interval '1d') AS series`), 'series.date', 'my_error_table.timestamp')
.debug();
附件是 Debug 的 SQL 输出。
select time_bucket('1 day', timestamp) AS daily, count(timestamp)
from my_errors_table
right join generate_series(date '2018-11-08', date '2018-11-15', interval '1d') AS series
on series = my_errors_table.timestamp
where device_id = ? and timestamp > ? and severity = ?
group by timestamp