Update client side lucene searching to work with nested JSON fields and fix bug with flattening nested JSON schema
This commit is contained in:
parent
cd5d370e7b
commit
d10d332b9f
5 changed files with 44 additions and 19 deletions
|
@ -410,6 +410,7 @@ export const getSchemaForDatasource = (asset, datasource, isForm = false) => {
|
||||||
jsonSchema = jsonSchema[keysToSchema[i]].schema
|
jsonSchema = jsonSchema[keysToSchema[i]].schema
|
||||||
}
|
}
|
||||||
schema = convertJSONSchemaToTableSchema(jsonSchema, true)
|
schema = convertJSONSchemaToTableSchema(jsonSchema, true)
|
||||||
|
console.log(schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we assume we're targeting an internal table or a plus
|
// Otherwise we assume we're targeting an internal table or a plus
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
export const convertJSONSchemaToTableSchema = jsonSchema => {
|
export const convertJSONSchemaToTableSchema = (
|
||||||
|
jsonSchema,
|
||||||
|
squashObjects = false
|
||||||
|
) => {
|
||||||
if (!jsonSchema) {
|
if (!jsonSchema) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (jsonSchema.schema) {
|
if (jsonSchema.schema) {
|
||||||
jsonSchema = jsonSchema.schema
|
jsonSchema = jsonSchema.schema
|
||||||
}
|
}
|
||||||
const keys = extractJSONSchemaKeys(jsonSchema)
|
const keys = extractJSONSchemaKeys(jsonSchema, squashObjects)
|
||||||
let schema = {}
|
let schema = {}
|
||||||
keys.forEach(({ key, type }) => {
|
keys.forEach(({ key, type }) => {
|
||||||
schema[key] = { type, name: key }
|
schema[key] = { type, name: key }
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
export let panel = ClientBindingPanel
|
export let panel = ClientBindingPanel
|
||||||
export let allowBindings = true
|
export let allowBindings = true
|
||||||
|
|
||||||
const BannedTypes = ["link", "attachment", "formula"]
|
const BannedTypes = ["link", "attachment", "formula", "json"]
|
||||||
|
|
||||||
$: fieldOptions = (schemaFields ?? [])
|
$: fieldOptions = (schemaFields ?? [])
|
||||||
.filter(field => !BannedTypes.includes(field.type))
|
.filter(field => !BannedTypes.includes(field.type))
|
||||||
|
|
|
@ -99,6 +99,7 @@ export const luceneQuery = (docs, query) => {
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return docs
|
return docs
|
||||||
}
|
}
|
||||||
|
|
||||||
// make query consistent first
|
// make query consistent first
|
||||||
query = cleanupQuery(query)
|
query = cleanupQuery(query)
|
||||||
|
|
||||||
|
@ -106,7 +107,9 @@ export const luceneQuery = (docs, query) => {
|
||||||
const match = (type, failFn) => doc => {
|
const match = (type, failFn) => doc => {
|
||||||
const filters = Object.entries(query[type] || {})
|
const filters = Object.entries(query[type] || {})
|
||||||
for (let i = 0; i < filters.length; i++) {
|
for (let i = 0; i < filters.length; i++) {
|
||||||
if (failFn(filters[i][0], filters[i][1], doc)) {
|
const [key, testValue] = filters[i]
|
||||||
|
const docValue = deepGet(doc, key)
|
||||||
|
if (failFn(docValue, testValue)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,38 +117,38 @@ export const luceneQuery = (docs, query) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process a string match (fails if the value does not start with the string)
|
// Process a string match (fails if the value does not start with the string)
|
||||||
const stringMatch = match("string", (key, value, doc) => {
|
const stringMatch = match("string", (docValue, testValue) => {
|
||||||
return !doc[key] || !doc[key].startsWith(value)
|
return !docValue || !docValue.startsWith(testValue)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Process a fuzzy match (treat the same as starts with when running locally)
|
// Process a fuzzy match (treat the same as starts with when running locally)
|
||||||
const fuzzyMatch = match("fuzzy", (key, value, doc) => {
|
const fuzzyMatch = match("fuzzy", (docValue, testValue) => {
|
||||||
return !doc[key] || !doc[key].startsWith(value)
|
return !docValue || !docValue.startsWith(testValue)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Process a range match
|
// Process a range match
|
||||||
const rangeMatch = match("range", (key, value, doc) => {
|
const rangeMatch = match("range", (docValue, testValue) => {
|
||||||
return !doc[key] || doc[key] < value.low || doc[key] > value.high
|
return !docValue || docValue < testValue.low || docValue > testValue.high
|
||||||
})
|
})
|
||||||
|
|
||||||
// Process an equal match (fails if the value is different)
|
// Process an equal match (fails if the value is different)
|
||||||
const equalMatch = match("equal", (key, value, doc) => {
|
const equalMatch = match("equal", (docValue, testValue) => {
|
||||||
return value != null && value !== "" && doc[key] !== value
|
return testValue != null && testValue !== "" && docValue !== testValue
|
||||||
})
|
})
|
||||||
|
|
||||||
// Process a not-equal match (fails if the value is the same)
|
// Process a not-equal match (fails if the value is the same)
|
||||||
const notEqualMatch = match("notEqual", (key, value, doc) => {
|
const notEqualMatch = match("notEqual", (docValue, testValue) => {
|
||||||
return value != null && value !== "" && doc[key] === value
|
return testValue != null && testValue !== "" && docValue === testValue
|
||||||
})
|
})
|
||||||
|
|
||||||
// Process an empty match (fails if the value is not empty)
|
// Process an empty match (fails if the value is not empty)
|
||||||
const emptyMatch = match("empty", (key, value, doc) => {
|
const emptyMatch = match("empty", docValue => {
|
||||||
return doc[key] != null && doc[key] !== ""
|
return docValue != null && docValue !== ""
|
||||||
})
|
})
|
||||||
|
|
||||||
// Process a not-empty match (fails is the value is empty)
|
// Process a not-empty match (fails is the value is empty)
|
||||||
const notEmptyMatch = match("notEmpty", (key, value, doc) => {
|
const notEmptyMatch = match("notEmpty", docValue => {
|
||||||
return doc[key] == null || doc[key] === ""
|
return docValue == null || docValue === ""
|
||||||
})
|
})
|
||||||
|
|
||||||
// Match a document against all criteria
|
// Match a document against all criteria
|
||||||
|
@ -202,3 +205,21 @@ export const luceneLimit = (docs, limit) => {
|
||||||
}
|
}
|
||||||
return docs.slice(0, numLimit)
|
return docs.slice(0, numLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a key within an object. The key supports dot syntax for retriving deep
|
||||||
|
* fields - e.g. "a.b.c".
|
||||||
|
* @param obj the object
|
||||||
|
* @param key the key
|
||||||
|
*/
|
||||||
|
const deepGet = (obj, key) => {
|
||||||
|
if (!obj || !key) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const split = key.split(".")
|
||||||
|
let value = obj
|
||||||
|
for (let i = 0; i < split.length; i++) {
|
||||||
|
value = value?.[split[i]]
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
export let schemaFields
|
export let schemaFields
|
||||||
export let filters = []
|
export let filters = []
|
||||||
|
|
||||||
const BannedTypes = ["link", "attachment", "formula"]
|
const BannedTypes = ["link", "attachment", "formula", "json"]
|
||||||
|
|
||||||
$: fieldOptions = (schemaFields ?? [])
|
$: fieldOptions = (schemaFields ?? [])
|
||||||
.filter(field => !BannedTypes.includes(field.type))
|
.filter(field => !BannedTypes.includes(field.type))
|
||||||
|
|
Loading…
Reference in a new issue