diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 8f4d96d5e8..f3353be3b2 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -1279,6 +1279,8 @@ describe.each([ { numbers: ["three"] }, ])) + // Not sure if this is correct behaviour but changing it would be a + // breaking change. it("finds all with empty list", () => expectQuery({ notContains: { numbers: [] } }).toContainExactly([ { numbers: ["one", "two"] }, diff --git a/packages/shared-core/src/filters.ts b/packages/shared-core/src/filters.ts index 4ccbc60641..2e7afa882b 100644 --- a/packages/shared-core/src/filters.ts +++ b/packages/shared-core/src/filters.ts @@ -425,10 +425,26 @@ export const runQuery = ( return testValue[f](item => _valueMatches(docValue, item)) } - const contains = match(SearchFilterOperator.CONTAINS, _contains("every")) + const contains = match( + SearchFilterOperator.CONTAINS, + (docValue: any, testValue: any) => { + if (Array.isArray(testValue) && testValue.length === 0) { + return true + } + return _contains("every")(docValue, testValue) + } + ) const notContains = match( SearchFilterOperator.NOT_CONTAINS, - not(_contains("every")) + (docValue: any, testValue: any) => { + // Not sure if this is logically correct, but at the time this code was + // written the search endpoint behaved this way and we wanted to make this + // local search match its behaviour, so we had to do this. + if (Array.isArray(testValue) && testValue.length === 0) { + return true + } + return not(_contains("every"))(docValue, testValue) + } ) const containsAny = match( SearchFilterOperator.CONTAINS_ANY,