diff --git a/packages/frontend-core/src/constants.js b/packages/frontend-core/src/constants.js index 4ac2a02f6c..1d3c31f54d 100644 --- a/packages/frontend-core/src/constants.js +++ b/packages/frontend-core/src/constants.js @@ -39,7 +39,7 @@ export const OperatorOptions = { label: "Contains", }, NotContains: { - value: "notEqual", + value: "notContains", label: "Does Not Contain", }, In: { diff --git a/packages/server/src/api/controllers/row/internalSearch.js b/packages/server/src/api/controllers/row/internalSearch.js index b60d72506b..c2e7905924 100644 --- a/packages/server/src/api/controllers/row/internalSearch.js +++ b/packages/server/src/api/controllers/row/internalSearch.js @@ -20,6 +20,7 @@ class QueryBuilder { notEmpty: {}, oneOf: {}, contains: {}, + notContains: {}, ...base, } this.limit = 50 @@ -125,6 +126,11 @@ class QueryBuilder { return this } + addNotContains(key, value) { + this.query.notContains[key] = value + return this + } + /** * Preprocesses a value before going into a lucene search. * Transforms strings to lowercase and wraps strings and bools in quotes. @@ -181,6 +187,10 @@ class QueryBuilder { return `${key}:(${andStatement})` } + const notContains = (key, value) => { + return "*:* AND NOT " + contains(key, value) + } + const oneOf = (key, value) => { if (!Array.isArray(value)) { if (typeof value === "string") { @@ -279,6 +289,9 @@ class QueryBuilder { if (this.query.contains) { build(this.query.contains, contains) } + if (this.query.notContains) { + build(this.query.notContains, notContains) + } // make sure table ID is always added as an AND if (tableId) { query = `(${query})`