Merge branch 'master' into cleanup-isolates

This commit is contained in:
Sam Rose 2024-03-06 15:10:56 +00:00 committed by GitHub
commit 373cbf7c73
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 127 additions and 51 deletions

View File

@ -390,24 +390,41 @@ export const runLuceneQuery = (docs: any[], query?: SearchQuery) => {
} }
) )
// Match a document against all criteria
const docMatch = (doc: any) => { const docMatch = (doc: any) => {
return ( const filterFunctions: Record<SearchQueryOperators, (doc: any) => boolean> =
stringMatch(doc) && {
fuzzyMatch(doc) && string: stringMatch,
rangeMatch(doc) && fuzzy: fuzzyMatch,
equalMatch(doc) && range: rangeMatch,
notEqualMatch(doc) && equal: equalMatch,
emptyMatch(doc) && notEqual: notEqualMatch,
notEmptyMatch(doc) && empty: emptyMatch,
oneOf(doc) && notEmpty: notEmptyMatch,
contains(doc) && oneOf: oneOf,
containsAny(doc) && contains: contains,
notContains(doc) containsAny: containsAny,
) notContains: notContains,
} }
// Process all docs const activeFilterKeys: SearchQueryOperators[] = Object.entries(query || {})
.filter(
([key, value]: [string, any]) =>
!["allOr", "onEmptyFilter"].includes(key) &&
value &&
Object.keys(value as Record<string, any>).length > 0
)
.map(([key]) => key as any)
const results: boolean[] = activeFilterKeys.map(filterKey => {
return filterFunctions[filterKey]?.(doc) ?? false
})
if (query!.allOr) {
return results.some(result => result === true)
} else {
return results.every(result => result === true)
}
}
return docs.filter(docMatch) return docs.filter(docMatch)
} }

View File

@ -47,10 +47,7 @@ describe("runLuceneQuery", () => {
}, },
] ]
function buildQuery( function buildQuery(filters: { [filterKey: string]: any }): SearchQuery {
filterKey: string,
value: { [key: string]: any }
): SearchQuery {
const query: SearchQuery = { const query: SearchQuery = {
string: {}, string: {},
fuzzy: {}, fuzzy: {},
@ -63,8 +60,13 @@ describe("runLuceneQuery", () => {
notContains: {}, notContains: {},
oneOf: {}, oneOf: {},
containsAny: {}, containsAny: {},
allOr: false,
} }
query[filterKey as SearchQueryOperators] = value
for (const filterKey in filters) {
query[filterKey as SearchQueryOperators] = filters[filterKey]
}
return query return query
} }
@ -73,16 +75,17 @@ describe("runLuceneQuery", () => {
}) })
it("should return matching rows for equal filter", () => { it("should return matching rows for equal filter", () => {
const query = buildQuery("equal", { const query = buildQuery({
order_status: 4, equal: { order_status: 4 },
}) })
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([1, 2]) expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([1, 2])
}) })
it("should return matching row for notEqual filter", () => { it("should return matching row for notEqual filter", () => {
const query = buildQuery("notEqual", { const query = buildQuery({
order_status: 4, notEqual: { order_status: 4 },
}) })
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([3]) expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([3])
}) })
@ -90,48 +93,56 @@ describe("runLuceneQuery", () => {
expect( expect(
runLuceneQuery( runLuceneQuery(
docs, docs,
buildQuery("fuzzy", { buildQuery({
description: "sm", fuzzy: { description: "sm" },
}) })
).map(row => row.description) ).map(row => row.description)
).toEqual(["Small box"]) ).toEqual(["Small box"])
expect( expect(
runLuceneQuery( runLuceneQuery(
docs, docs,
buildQuery("string", { buildQuery({
description: "SM", string: { description: "SM" },
}) })
).map(row => row.description) ).map(row => row.description)
).toEqual(["Small box"]) ).toEqual(["Small box"])
}) })
it("should return rows within a range filter", () => { it("should return rows within a range filter", () => {
const query = buildQuery("range", { const query = buildQuery({
range: {
customer_id: { customer_id: {
low: 500, low: 500,
high: 1000, high: 1000,
}, },
},
}) })
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([3]) expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([3])
}) })
it("should return rows with numeric strings within a range filter", () => { it("should return rows with numeric strings within a range filter", () => {
const query = buildQuery("range", { const query = buildQuery({
range: {
customer_id: { customer_id: {
low: "500", low: "500",
high: "1000", high: "1000",
}, },
},
}) })
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([3]) expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([3])
}) })
it("should return rows with ISO date strings within a range filter", () => { it("should return rows with ISO date strings within a range filter", () => {
const query = buildQuery("range", { const query = buildQuery({
range: {
order_date: { order_date: {
low: "2016-01-04T00:00:00.000Z", low: "2016-01-04T00:00:00.000Z",
high: "2016-01-11T00:00:00.000Z", high: "2016-01-11T00:00:00.000Z",
}, },
},
}) })
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([2]) expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([2])
}) })
@ -150,40 +161,88 @@ describe("runLuceneQuery", () => {
label: "", label: "",
}, },
] ]
const query = buildQuery("range", {
const query = buildQuery({
range: {
order_date: { order_date: {
low: "2016-01-04T00:00:00.000Z", low: "2016-01-04T00:00:00.000Z",
high: "2016-01-11T00:00:00.000Z", high: "2016-01-11T00:00:00.000Z",
}, },
},
}) })
expect(runLuceneQuery(docs, query)).toEqual(docs) expect(runLuceneQuery(docs, query)).toEqual(docs)
}) })
it("should return rows with matches on empty filter", () => { it("should return rows with matches on empty filter", () => {
const query = buildQuery("empty", { const query = buildQuery({
empty: {
label: null, label: null,
},
}) })
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([1]) expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([1])
}) })
it("should return rows with matches on notEmpty filter", () => { it("should return rows with matches on notEmpty filter", () => {
const query = buildQuery("notEmpty", { const query = buildQuery({
notEmpty: {
label: null, label: null,
},
}) })
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([2, 3]) expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([2, 3])
}) })
test.each([[523, 259], "523,259"])( test.each([[523, 259], "523,259"])(
"should return rows with matches on numeric oneOf filter", "should return rows with matches on numeric oneOf filter",
input => { input => {
let query = buildQuery("oneOf", { const query = buildQuery({
oneOf: {
customer_id: input, customer_id: input,
},
}) })
expect(runLuceneQuery(docs, query).map(row => row.customer_id)).toEqual([ expect(runLuceneQuery(docs, query).map(row => row.customer_id)).toEqual([
259, 523, 259, 523,
]) ])
} }
) )
test.each([
[false, []],
[true, [1, 2, 3]],
])("should return %s if allOr is %s ", (allOr, expectedResult) => {
const query = buildQuery({
allOr,
oneOf: { staff_id: [10] },
contains: { description: ["box"] },
})
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual(
expectedResult
)
})
it("should return matching results if allOr is true and only one filter matches with different operands", () => {
const query = buildQuery({
allOr: true,
equal: { order_status: 4 },
oneOf: { label: ["FRAGILE"] },
})
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([1, 2])
})
it("should handle when a value is null or undefined", () => {
const query = buildQuery({
allOr: true,
equal: { order_status: null },
oneOf: { label: ["FRAGILE"] },
})
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([2])
})
}) })
describe("buildLuceneQuery", () => { describe("buildLuceneQuery", () => {