Making progress.
This commit is contained in:
parent
ae6539161f
commit
22bf0d05ad
|
@ -1706,7 +1706,7 @@ describe.each([
|
|||
})
|
||||
|
||||
describe("contains", () => {
|
||||
it.only("successfully finds a row", () =>
|
||||
it("successfully finds a row", () =>
|
||||
expectQuery({ contains: { users: [user1._id] } }).toContainExactly([
|
||||
{ users: [{ _id: user1._id }] },
|
||||
{ users: [{ _id: user1._id }, { _id: user2._id }] },
|
||||
|
@ -1763,9 +1763,12 @@ describe.each([
|
|||
|
||||
// This will never work for Lucene.
|
||||
!isLucene &&
|
||||
// It also can't work for in-memory searching because the related table name
|
||||
// isn't available.
|
||||
!isInMemory &&
|
||||
describe("relations", () => {
|
||||
let otherTable: Table
|
||||
let rows: Row[]
|
||||
let otherRows: Row[]
|
||||
|
||||
beforeAll(async () => {
|
||||
otherTable = await createTable({
|
||||
|
@ -1785,7 +1788,7 @@ describe.each([
|
|||
},
|
||||
})
|
||||
|
||||
rows = await Promise.all([
|
||||
otherRows = await Promise.all([
|
||||
config.api.row.save(otherTable._id!, { one: "foo" }),
|
||||
config.api.row.save(otherTable._id!, { one: "bar" }),
|
||||
])
|
||||
|
@ -1793,18 +1796,22 @@ describe.each([
|
|||
await Promise.all([
|
||||
config.api.row.save(table._id!, {
|
||||
two: "foo",
|
||||
other: [rows[0]._id],
|
||||
other: [otherRows[0]._id],
|
||||
}),
|
||||
config.api.row.save(table._id!, {
|
||||
two: "bar",
|
||||
other: [rows[1]._id],
|
||||
other: [otherRows[1]._id],
|
||||
}),
|
||||
])
|
||||
|
||||
rows = await config.api.row.fetch(table._id!)
|
||||
})
|
||||
|
||||
it("can search through relations", () =>
|
||||
expectQuery({
|
||||
equal: { [`${otherTable.name}.one`]: "foo" },
|
||||
}).toContainExactly([{ two: "foo", other: [{ _id: rows[0]._id }] }]))
|
||||
}).toContainExactly([
|
||||
{ two: "foo", other: [{ _id: otherRows[0]._id }] },
|
||||
]))
|
||||
})
|
||||
})
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
import dayjs from "dayjs"
|
||||
import { OperatorOptions, SqlNumberTypeRangeMap } from "./constants"
|
||||
import { deepGet, schema } from "./helpers"
|
||||
import _ from "lodash"
|
||||
|
||||
const HBS_REGEX = /{{([^{].*?)}}/g
|
||||
|
||||
|
@ -339,15 +340,36 @@ export const runQuery = (
|
|||
}
|
||||
)
|
||||
|
||||
// This function exists to check that either the docValue is equal to the
|
||||
// testValue, or if the docValue is an object or array of objects, that the
|
||||
// _id of the docValue is equal to the testValue.
|
||||
const _valueMatches = (docValue: any, testValue: any) => {
|
||||
if (Array.isArray(docValue)) {
|
||||
for (const item of docValue) {
|
||||
if (_valueMatches(item, testValue)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if (typeof docValue === "object" && typeof testValue === "string") {
|
||||
return docValue._id === testValue
|
||||
}
|
||||
|
||||
return docValue === testValue
|
||||
}
|
||||
|
||||
const not =
|
||||
<T extends any[]>(f: (...args: T) => boolean) =>
|
||||
(...args: T): boolean =>
|
||||
!f(...args)
|
||||
|
||||
const _equal = (docValue: any, testValue: any) => docValue === testValue
|
||||
|
||||
const equalMatch = match(SearchFilterOperator.EQUAL, _equal)
|
||||
const notEqualMatch = match(SearchFilterOperator.NOT_EQUAL, not(_equal))
|
||||
const equalMatch = match(SearchFilterOperator.EQUAL, _valueMatches)
|
||||
const notEqualMatch = match(
|
||||
SearchFilterOperator.NOT_EQUAL,
|
||||
not(_valueMatches)
|
||||
)
|
||||
|
||||
const _empty = (docValue: any) => {
|
||||
if (typeof docValue === "string") {
|
||||
|
@ -379,54 +401,40 @@ export const runQuery = (
|
|||
return false
|
||||
}
|
||||
|
||||
return testValue.includes(docValue)
|
||||
return testValue.some(item => _valueMatches(docValue, item))
|
||||
}
|
||||
)
|
||||
|
||||
const _contains =
|
||||
(f: "some" | "every") => (docValue: any, testValue: any) => {
|
||||
if (!Array.isArray(docValue)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (typeof testValue === "string") {
|
||||
testValue = testValue.split(",")
|
||||
if (typeof docValue[0] === "number") {
|
||||
testValue = testValue.map((item: string) => parseFloat(item))
|
||||
}
|
||||
}
|
||||
|
||||
if (!Array.isArray(testValue)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return testValue[f](item => _valueMatches(docValue, item))
|
||||
}
|
||||
|
||||
const contains = match(SearchFilterOperator.CONTAINS, _contains("every"))
|
||||
const notContains = match(
|
||||
SearchFilterOperator.NOT_CONTAINS,
|
||||
not(_contains("every"))
|
||||
)
|
||||
const containsAny = match(
|
||||
SearchFilterOperator.CONTAINS_ANY,
|
||||
(docValue: any, testValue: any) => {
|
||||
if (!Array.isArray(docValue)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (typeof testValue === "string") {
|
||||
testValue = testValue.split(",")
|
||||
if (typeof docValue[0] === "number") {
|
||||
testValue = testValue.map((item: string) => parseFloat(item))
|
||||
}
|
||||
}
|
||||
|
||||
if (!Array.isArray(testValue)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return testValue.some(item => docValue.includes(item))
|
||||
}
|
||||
_contains("some")
|
||||
)
|
||||
|
||||
const _contains = (docValue: any, testValue: any) => {
|
||||
if (!Array.isArray(docValue)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (typeof testValue === "string") {
|
||||
testValue = testValue.split(",")
|
||||
if (typeof docValue[0] === "number") {
|
||||
testValue = testValue.map((item: string) => parseFloat(item))
|
||||
}
|
||||
}
|
||||
|
||||
if (!Array.isArray(testValue)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return testValue.every(item => docValue.includes(item))
|
||||
}
|
||||
|
||||
const contains = match(SearchFilterOperator.CONTAINS, _contains)
|
||||
const notContains = match(SearchFilterOperator.NOT_CONTAINS, not(_contains))
|
||||
|
||||
const docMatch = (doc: Record<string, any>) => {
|
||||
const filterFunctions = {
|
||||
string: stringMatch,
|
||||
|
|
Loading…
Reference in New Issue