Update test lucene builder and add more tests

This commit is contained in:
Peter Clement 2024-03-04 09:48:47 +00:00
parent 2933571c62
commit e3c514e45a
2 changed files with 116 additions and 69 deletions

View File

@ -391,43 +391,32 @@ export const runLuceneQuery = (docs: any[], query?: SearchQuery) => {
) )
const docMatch = (doc: any) => { const docMatch = (doc: any) => {
// Determine active filters based on query object const filterFunctions = {
const activeFilterKeys = Object.entries(query || {}) string: stringMatch,
fuzzy: fuzzyMatch,
range: rangeMatch,
equal: equalMatch,
notEqual: notEqualMatch,
empty: emptyMatch,
notEmpty: notEmptyMatch,
oneOf: oneOf,
contains: contains,
containsAny: containsAny,
notContains: notContains,
}
const activeFilterKeys: (keyof typeof filterFunctions)[] = Object.entries(
query
)
.filter( .filter(
([key, value]) => ([key, value]: [string, any]) =>
!["allOr", "onEmptyFilter"].includes(key) && !["allOr", "onEmptyFilter"].includes(key) &&
Object.keys(value).length > 0 Object.keys(value as Record<string, any>).length > 0
) )
.map(([key]) => key) .map(([key]) => key as keyof typeof filterFunctions)
// Apply filters dynamically based on activeFilterKeys const results: boolean[] = activeFilterKeys.map(filterKey => {
const results = activeFilterKeys.map(filterKey => { const filterFunction = filterFunctions[filterKey]
switch (filterKey) { return filterFunction ? filterFunction(doc) : true
case "string":
return stringMatch(doc)
case "fuzzy":
return fuzzyMatch(doc)
case "range":
return rangeMatch(doc)
case "equal":
return equalMatch(doc)
case "notEqual":
return notEqualMatch(doc)
case "empty":
return emptyMatch(doc)
case "notEmpty":
return notEmptyMatch(doc)
case "oneOf":
return oneOf(doc)
case "contains":
return contains(doc)
case "containsAny":
return containsAny(doc)
case "notContains":
return notContains(doc)
default:
return true // If the filter type is not recognized, default to true (assuming pass)
}
}) })
if (query!.allOr) { if (query!.allOr) {
@ -436,7 +425,7 @@ export const runLuceneQuery = (docs: any[], query?: SearchQuery) => {
return results.every(result => result === true) return results.every(result => result === true)
} }
} }
// Process all docs
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({
customer_id: { range: {
low: 500, customer_id: {
high: 1000, low: 500,
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({
customer_id: { range: {
low: "500", customer_id: {
high: "1000", low: "500",
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({
order_date: { range: {
low: "2016-01-04T00:00:00.000Z", order_date: {
high: "2016-01-11T00:00:00.000Z", low: "2016-01-04T00: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,87 @@ describe("runLuceneQuery", () => {
label: "", label: "",
}, },
] ]
const query = buildQuery("range", {
order_date: { const query = buildQuery({
low: "2016-01-04T00:00:00.000Z", range: {
high: "2016-01-11T00:00:00.000Z", order_date: {
low: "2016-01-04T00: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({
label: null, empty: {
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({
label: null, notEmpty: {
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({
customer_id: input, oneOf: {
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,
]) ])
} }
) )
it("should return matching results if allOr is true and only one filter matches", () => {
const query = buildQuery({
allOr: true,
oneOf: { staff_id: [10] },
contains: { description: ["box"] },
})
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([
1, 2, 3,
])
})
// what should the name of this test be if it's the same test as above but with different operands
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 return nothing if allOr is false and only one filter matches", () => {
const query = buildQuery({
allOr: false,
oneOf: { staff_id: [10] },
contains: { description: ["box"] },
})
expect(runLuceneQuery(docs, query).map(row => row.order_id)).toEqual([])
})
}) })
describe("buildLuceneQuery", () => { describe("buildLuceneQuery", () => {