Further enhancement, client library sends up the column it wants enriched and then we can ignore everything else, makes a big difference for enriching users (with a lot of relationships).
This commit is contained in:
parent
069fd33964
commit
3e2f9dfc4e
|
@ -9,7 +9,9 @@ export const buildRelationshipEndpoints = API => ({
|
|||
if (!tableId || !rowId) {
|
||||
return []
|
||||
}
|
||||
const response = await API.get({ url: `/api/${tableId}/${rowId}/enrich` })
|
||||
const response = await API.get({
|
||||
url: `/api/${tableId}/${rowId}/enrich?field=${fieldName}`,
|
||||
})
|
||||
if (!fieldName) {
|
||||
return response || []
|
||||
} else {
|
||||
|
|
|
@ -224,14 +224,15 @@ export async function bulkDestroy(ctx: UserCtx) {
|
|||
}
|
||||
|
||||
export async function fetchEnrichedRow(ctx: UserCtx) {
|
||||
const fieldName = ctx.request.query.field as string | undefined
|
||||
const db = context.getAppDB()
|
||||
const tableId = utils.getTableId(ctx)
|
||||
const rowId = ctx.params.rowId
|
||||
const rowId = ctx.params.rowId as string
|
||||
// need table to work out where links go in row, as well as the link docs
|
||||
let response = await Promise.all([
|
||||
sdk.tables.getTable(tableId),
|
||||
utils.findRow(ctx, tableId, rowId),
|
||||
linkRows.getLinkDocuments({ tableId, rowId }),
|
||||
linkRows.getLinkDocuments({ tableId, rowId, fieldName }),
|
||||
])
|
||||
const table = response[0] as Table
|
||||
const row = response[1] as Row
|
||||
|
@ -248,8 +249,13 @@ export async function fetchEnrichedRow(ctx: UserCtx) {
|
|||
let final = []
|
||||
for (let linkTable of linkTables) {
|
||||
const relatedRows = linkedRows.filter(row => row.tableId === linkTable._id)
|
||||
// include the row being enriched for performance reasons, don't need to fetch it to include
|
||||
final = final.concat(
|
||||
outputProcessing(linkTable, relatedRows, { preserveLinks: true })
|
||||
outputProcessing(linkTable, relatedRows, {
|
||||
// have to clone to avoid JSON cycle
|
||||
fromRow: cloneDeep(row),
|
||||
squash: true,
|
||||
})
|
||||
)
|
||||
}
|
||||
// finalise the promises
|
||||
|
|
|
@ -146,9 +146,14 @@ export async function updateLinks(args: {
|
|||
* This is required for formula fields, this may only be utilised internally (for now).
|
||||
* @param {object} table The table from which the rows originated.
|
||||
* @param {array<object>} rows The rows which are to be enriched.
|
||||
* @param {object} opts optional - options like passing in a base row to use for enrichment.
|
||||
* @return {Promise<*>} returns the rows with all of the enriched relationships on it.
|
||||
*/
|
||||
export async function attachFullLinkedDocs(table: Table, rows: Row[]) {
|
||||
export async function attachFullLinkedDocs(
|
||||
table: Table,
|
||||
rows: Row[],
|
||||
opts?: { fromRow?: Row }
|
||||
) {
|
||||
const linkedTableIds = getLinkedTableIDs(table)
|
||||
if (linkedTableIds.length === 0) {
|
||||
return rows
|
||||
|
@ -158,20 +163,34 @@ export async function attachFullLinkedDocs(table: Table, rows: Row[]) {
|
|||
getLinksForRows(rows),
|
||||
sdk.tables.getTables(linkedTableIds),
|
||||
])
|
||||
// find the links that pertain to one of the rows that is being enriched
|
||||
const links = (response[0] as LinkDocumentValue[]).filter(link =>
|
||||
rows.some(row => row._id === link.thisId)
|
||||
)
|
||||
// if fromRow has been passed in, then we don't need to fetch it (optimisation)
|
||||
let linksWithoutFromRow = links
|
||||
if (opts?.fromRow) {
|
||||
linksWithoutFromRow = links.filter(link => link.id !== opts?.fromRow?._id)
|
||||
}
|
||||
const linkedTables = response[1] as Table[]
|
||||
// clear any existing links that could be dupe'd
|
||||
rows = clearRelationshipFields(table, rows)
|
||||
// now get the docs and combine into the rows
|
||||
let linked = await getFullLinkedDocs(links)
|
||||
let linked = []
|
||||
if (linksWithoutFromRow.length > 0) {
|
||||
linked = await getFullLinkedDocs(linksWithoutFromRow)
|
||||
}
|
||||
for (let row of rows) {
|
||||
for (let link of links.filter(link => link.thisId === row._id)) {
|
||||
if (row[link.fieldName] == null) {
|
||||
row[link.fieldName] = []
|
||||
}
|
||||
const linkedRow = linked.find(row => row._id === link.id)
|
||||
let linkedRow: Row
|
||||
if (opts?.fromRow && opts?.fromRow?._id === link.id) {
|
||||
linkedRow = opts.fromRow!
|
||||
} else {
|
||||
linkedRow = linked.find(row => row._id === link.id)
|
||||
}
|
||||
if (linkedRow) {
|
||||
const linkedTableId =
|
||||
linkedRow.tableId || getRelatedTableForField(table, link.fieldName)
|
||||
|
|
|
@ -35,19 +35,22 @@ export const IncludeDocs = {
|
|||
export async function getLinkDocuments(args: {
|
||||
tableId?: string
|
||||
rowId?: string
|
||||
includeDocs?: any
|
||||
fieldName?: string
|
||||
includeDocs?: boolean
|
||||
}): Promise<LinkDocumentValue[] | LinkDocument[]> {
|
||||
const { tableId, rowId, includeDocs } = args
|
||||
const { tableId, rowId, fieldName, includeDocs } = args
|
||||
const db = context.getAppDB()
|
||||
let params: any
|
||||
if (rowId != null) {
|
||||
if (rowId) {
|
||||
params = { key: [tableId, rowId] }
|
||||
}
|
||||
// only table is known
|
||||
else {
|
||||
params = { startKey: [tableId], endKey: [tableId, {}] }
|
||||
}
|
||||
params.include_docs = !!includeDocs
|
||||
if (includeDocs) {
|
||||
params.include_docs = true
|
||||
}
|
||||
try {
|
||||
let linkRows = (await db.query(getQueryIndex(ViewName.LINK), params)).rows
|
||||
// filter to get unique entries
|
||||
|
@ -67,6 +70,11 @@ export async function getLinkDocuments(args: {
|
|||
return unique
|
||||
})
|
||||
|
||||
// filter down to just the required field name
|
||||
if (fieldName) {
|
||||
linkRows = linkRows.filter(link => link.value.fieldName === fieldName)
|
||||
}
|
||||
// return docs if docs requested, otherwise just the value information
|
||||
if (includeDocs) {
|
||||
return linkRows.map(row => row.doc) as LinkDocument[]
|
||||
} else {
|
||||
|
|
|
@ -104,7 +104,7 @@ async function getTable(tableId: string): Promise<Table> {
|
|||
const table = await getExternalTable(datasourceId, tableName)
|
||||
return { ...table, sql: isSQL(datasource) }
|
||||
} else {
|
||||
return db.get(tableId)
|
||||
return db.get<Table>(tableId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ export async function inputProcessing(
|
|||
export async function outputProcessing<T extends Row[] | Row>(
|
||||
table: Table,
|
||||
rows: T,
|
||||
opts: { squash?: boolean; preserveLinks?: boolean } = {
|
||||
opts: { squash?: boolean; preserveLinks?: boolean; fromRow?: Row } = {
|
||||
squash: true,
|
||||
preserveLinks: false,
|
||||
}
|
||||
|
@ -216,7 +216,9 @@ export async function outputProcessing<T extends Row[] | Row>(
|
|||
}
|
||||
// attach any linked row information
|
||||
let enriched = !opts.preserveLinks
|
||||
? await linkRows.attachFullLinkedDocs(table, safeRows)
|
||||
? await linkRows.attachFullLinkedDocs(table, safeRows, {
|
||||
fromRow: opts?.fromRow,
|
||||
})
|
||||
: safeRows
|
||||
|
||||
// process formulas
|
||||
|
|
Loading…
Reference in New Issue