From b160af6603297873d1a18882373d51262d83506e Mon Sep 17 00:00:00 2001 From: Mel O'Hagan Date: Wed, 27 Jul 2022 13:02:46 +0100 Subject: [PATCH] Has any filter InternalDB --- packages/frontend-core/src/constants.js | 4 ++++ packages/frontend-core/src/utils/lucene.js | 3 ++- .../src/api/controllers/row/internalSearch.js | 21 +++++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/frontend-core/src/constants.js b/packages/frontend-core/src/constants.js index 71c9019750..c55dcd3f8f 100644 --- a/packages/frontend-core/src/constants.js +++ b/packages/frontend-core/src/constants.js @@ -46,6 +46,10 @@ export const OperatorOptions = { value: "oneOf", label: "Is in", }, + ContainsAny: { + value: "containsAny", + label: "Has any" + }, } // Cookie names diff --git a/packages/frontend-core/src/utils/lucene.js b/packages/frontend-core/src/utils/lucene.js index b27296af37..51c5ab2f72 100644 --- a/packages/frontend-core/src/utils/lucene.js +++ b/packages/frontend-core/src/utils/lucene.js @@ -32,7 +32,7 @@ export const getValidOperatorsForType = type => { } else if (type === "options") { return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] } else if (type === "array") { - return [Op.Contains, Op.NotContains, Op.Empty, Op.NotEmpty] + return [Op.Contains, Op.NotContains, Op.Empty, Op.NotEmpty, Op.ContainsAny] } else if (type === "boolean") { return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty] } else if (type === "longform") { @@ -94,6 +94,7 @@ export const buildLuceneQuery = filter => { contains: {}, notContains: {}, oneOf: {}, + containsAny: {}, } if (Array.isArray(filter)) { filter.forEach(expression => { diff --git a/packages/server/src/api/controllers/row/internalSearch.js b/packages/server/src/api/controllers/row/internalSearch.js index c2e7905924..5152b75124 100644 --- a/packages/server/src/api/controllers/row/internalSearch.js +++ b/packages/server/src/api/controllers/row/internalSearch.js @@ -21,6 +21,7 @@ class QueryBuilder { oneOf: {}, contains: {}, notContains: {}, + containsAny: {}, ...base, } this.limit = 50 @@ -131,6 +132,11 @@ class QueryBuilder { return this } + addContainsAny(key, value) { + this.query.containsAny[key] = value + return this + } + /** * Preprocesses a value before going into a lucene search. * Transforms strings to lowercase and wraps strings and bools in quotes. @@ -176,21 +182,25 @@ class QueryBuilder { return `${key}:${builder.preprocess(value, allPreProcessingOpts)}` } - const contains = (key, value) => { + const contains = (key, value, mode = "AND") => { if (!Array.isArray(value) || value.length === 0) { return null } - let andStatement = `${builder.preprocess(value[0], { escape: true })}` + let statement = `${builder.preprocess(value[0], { escape: true })}` for (let i = 1; i < value.length; i++) { - andStatement += ` AND ${builder.preprocess(value[i], { escape: true })}` + statement += ` ${mode} ${builder.preprocess(value[i], { escape: true })}` } - return `${key}:(${andStatement})` + return `${key}:(${statement})` } const notContains = (key, value) => { return "*:* AND NOT " + contains(key, value) } + const containsAny = (key, value) => { + return contains(key, value, "OR") + } + const oneOf = (key, value) => { if (!Array.isArray(value)) { if (typeof value === "string") { @@ -292,6 +302,9 @@ class QueryBuilder { if (this.query.notContains) { build(this.query.notContains, notContains) } + if (this.query.containsAny) { + build(this.query.containsAny, containsAny) + } // make sure table ID is always added as an AND if (tableId) { query = `(${query})`