Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: MongoDB-like Filtering #270

Closed
wants to merge 12 commits into from
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
21 changes: 21 additions & 0 deletions plugins/mongo_filter/README.md
Original file line number Diff line number Diff line change
@@ -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 )
```
62 changes: 62 additions & 0 deletions plugins/mongo_filter/index.js
Original file line number Diff line number Diff line change
@@ -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<Object>
* }} API
* promql: (query: string, startNS: number, endNS: number, limit: number) => Promise<Object> //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
5 changes: 5 additions & 0 deletions plugins/mongo_filter/plugnplay.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
id: mongo_filter
name: Format Output
description: Filter JSON using MongoDB functions
loader: index.js
type: custom_processor
Loading