commit 417e09b033a1e5d2fc7584ee0540b50d5dc4942b
parent 5b41a5193025a7a4db19f984c1d16651b28ffb61
Author: finwo <finwo@pm.me>
Date: Tue, 31 May 2022 15:45:45 +0200
Merge pull request #72 from paulcanning/feature/number-comparison
Add number comparison filtering.
Diffstat:
2 files changed, 108 insertions(+), 0 deletions(-)
diff --git a/src/filters/number/comparison.js b/src/filters/number/comparison.js
@@ -0,0 +1,48 @@
+const field = require('../../field');
+
+module.exports = {
+ detect : function (query) {
+ if (!query) {
+ return false;
+ }
+ if ('object' !== typeof query) {
+ return false;
+ }
+ if (!query.term) {
+ return false;
+ }
+ return Array.isArray(query.term.match(/^[<=>]+/));
+ },
+ compile: function (query) {
+ query.similarity = query.similarity || 0;
+ return function (data) {
+ return field(query.field, data, function (value) {
+ let sign, num;
+ value = parseFloat(value);
+ if (sign = query.term.match(/^[<=>]+/)) {
+ [sign] = sign;
+ }
+ num = query.term.match(/[0-9.]+/);
+ if (!num) {
+ return false;
+ }
+ num = Number(num[0]);
+ if (sign) {
+ if (sign === '>') {
+ return value > num;
+ } else if (sign === '>=') {
+ return value >= num;
+ } else if (sign === '<') {
+ return value < num;
+ } else if (sign === '<=') {
+ return value <= num;
+ } else {
+ throw new Error(`Invalid sign: ${sign}`);
+ }
+ } else {
+ return value === num;
+ }
+ });
+ };
+ },
+};
diff --git a/src/filters/number/comparison.test.js b/src/filters/number/comparison.test.js
@@ -0,0 +1,60 @@
+const tape = require('tape');
+const comparison = require('./comparison');
+
+tape('filter.number.comparison -- structure', async t => {
+ t.plan(2);
+ t.ok('detect' in comparison, 'comparison filter has detect method');
+ t.ok('compile' in comparison, 'comparison filter has compile method');
+});
+
+tape('filter.number.comparison -- detect', async t => {
+ t.plan(9);
+ t.notOk(comparison.detect(false), 'contains.detect doesn\'t trigger on false query');
+ t.notOk(comparison.detect(null), 'contains.detect doesn\'t trigger on null query');
+ t.notOk(comparison.detect(true), 'contains.detect doesn\'t trigger on true query');
+ t.notOk(comparison.detect([]), 'contains.detect doesn\'t trigger on empty array query');
+ t.notOk(comparison.detect({}), 'contains.detect doesn\'t trigger on empty object query');
+ t.notOk(comparison.detect({ field: 'something' }), 'contains.detect doesn\'t trigger on termless query');
+ t.notOk(comparison.detect({ term: 'something' }), 'contains.detect doesn\'t trigger on fieldless query');
+ t.ok(comparison.detect({ field: 'hello', term: '>1' }), 'contains.detect triggers on properly structured query');
+ t.notOk(comparison.detect({ field: 'hello', term: '1' }), 'contains.detect doesn\'t trigger on query with no comparator');
+});
+
+tape('filter.number.comparison, gt -- compile', async t => {
+ t.plan(3);
+
+ const extractor = comparison.compile({ field: 'age', term: '>21' });
+ t.equal(typeof extractor, 'function', 'comparison.compile returns a function');
+
+ t.ok(extractor({ age: 22 }), 'finds term in comparison');
+ t.notOk(extractor({ age: 21 }), 'doesn\'t find term in comparison');
+});
+tape('filter.number.comparison, gte -- compile', async t => {
+ t.plan(4);
+
+ const extractor = comparison.compile({ field: 'age', term: '>=21' });
+ t.equal(typeof extractor, 'function', 'comparison.compile returns a function');
+
+ t.ok(extractor({ age: 22 }), 'finds term in comparison');
+ t.ok(extractor({ age: 21 }), 'finds term in comparison');
+ t.notOk(extractor({ age: 20 }), 'doesn\'t find term in comparison');
+});
+tape('filter.number.comparison, lt -- compile', async t => {
+ t.plan(3);
+
+ const extractor = comparison.compile({ field: 'age', term: '<21' });
+ t.equal(typeof extractor, 'function', 'comparison.compile returns a function');
+
+ t.ok(extractor({ age: 20 }), 'finds term in comparison');
+ t.notOk(extractor({ age: 21 }), 'doesn\'t find term in comparison');
+});
+tape('filter.number.comparison, lte -- compile', async t => {
+ t.plan(4);
+
+ const extractor = comparison.compile({ field: 'age', term: '<=21' });
+ t.equal(typeof extractor, 'function', 'comparison.compile returns a function');
+
+ t.ok(extractor({ age: 20 }), 'finds term in comparison');
+ t.ok(extractor({ age: 21 }), 'finds term in comparison');
+ t.notOk(extractor({ age: 22 }), 'doesn\'t find term in comparison');
+});