diff --git a/package.json b/package.json index 36c565f3..124a0be3 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "handlebars": "^4.7.7", "handlebars-helpers": "^0.9.8", "logfmt": "^1.3.2", + "mongo-query-compiler": "^1.0.4", "json-stable-stringify": "^1.0.1", "jsonic": "^0.3.1", "patch-package": "^6.4.7", diff --git a/plugins/mongo_filter/README.md b/plugins/mongo_filter/README.md new file mode 100644 index 00000000..ddbbb21a --- /dev/null +++ b/plugins/mongo_filter/README.md @@ -0,0 +1,21 @@ +## qryn-plugin + +### mongo + +This plugin uses the [Mongo Query Compiler](https://github.com/aptivator/mongo-query-compiler-docs) library to transpile mongodb-like +query objects into a JavaScript filtering functions to be used with any array's .filter() method to isolate the needed data subset. + +### Example + +Original LogQL Selector: +``` +{type="people"} |="alive" | json +``` + +Mongo Filter: +``` +mongo({stream: { event: { $exists: true }}}, {type="people"} |="alive" | json) +``` +``` +mongo({$where: 'this.stream.event === "user"'}, {type="people"} |="alive" | json ) +``` diff --git a/plugins/mongo_filter/index.js b/plugins/mongo_filter/index.js new file mode 100644 index 00000000..e7bacf2d --- /dev/null +++ b/plugins/mongo_filter/index.js @@ -0,0 +1,62 @@ +const { PluginLoaderBase } = require('plugnplay') +const { compileMongoQuery } = require('mongo-query-compiler') + +/** + +Mongodb-like JSON filtering output processor. +Usage: mongo({age: {$exists: true}}, {type="people"} + +**/ + +/** + * @class Plugin + * @property {string} query + * @property start {number} start in NS + * @property end {string} end in NS + * @property type {string} promql or logql + * @property limit {number} + * @property {{ + * logql: (query: string, startNS: number, endNS: number, limit: number) => Promise + * }} API + * promql: (query: string, startNS: number, endNS: number, limit: number) => Promise //not implemented + */ +class Plugin { + /** + * @method + * @name check + * @this {Plg} + * @returns {boolean} if this plugin is usable for the query + */ + check () { + return this.query.match(/^mongo\(.+\)\s*$/) + } + + /** + * @method + * @name process + * @this {Plg} + * @returns {Promise<{type: string, out: string}>} The raw output + */ + async process () { + const match = this.query.match(/^mongo\({(.+)},\s*(.+)\)$/) + let response = await this.API.logql(match[2], this.start, this.end, this.limit) + + // Sanity Check. What error should this return? + if (!match || !match[1] || !match[2]) return response; + + // Filter using Mongo Query Compiler + let filterer = compileMongoQuery(match[1]); + response.data.result = response.data.result.filter(filterer); + return { + type: 'application/json', + out: response + } + } +} +class Plg extends PluginLoaderBase { + exportSync (api) { + return new Plugin() + } +} + +module.exports = Plg diff --git a/plugins/mongo_filter/plugnplay.yml b/plugins/mongo_filter/plugnplay.yml new file mode 100644 index 00000000..bd33ddfc --- /dev/null +++ b/plugins/mongo_filter/plugnplay.yml @@ -0,0 +1,5 @@ +id: mongo_filter +name: Format Output +description: Filter JSON using MongoDB functions +loader: index.js +type: custom_processor