budibase/packages/core/src/indexApi/buildIndex.js

216 lines
5.7 KiB
JavaScript
Raw Normal View History

import { filter, includes, some } from "lodash/fp"
import { getAllIdsIterator } from "../indexing/allIds"
2019-07-15 08:12:52 +02:00
import {
getFlattenedHierarchy,
getRecordNodeById,
getNode,
isIndex,
isRecord,
getAllowedRecordNodesForIndex,
2019-07-15 08:12:52 +02:00
fieldReversesReferenceToIndex,
} from "../templateApi/hierarchy"
import { joinKey, apiWrapper, events, $ } from "../common"
2019-07-15 08:12:52 +02:00
import {
createBuildIndexFolder,
transactionForBuildIndex,
} from "../transactions/create"
import { permission } from "../authApi/permissions"
import { BadRequestError } from "../common/errors"
2019-07-15 08:12:52 +02:00
/** rebuilds an index
* @param {object} app - the application container
* @param {string} indexNodeKey - node key of the index, which the index belongs to
*/
export const buildIndex = app => async indexNodeKey =>
apiWrapper(
app,
events.indexApi.buildIndex,
permission.manageIndex.isAuthorized,
{ indexNodeKey },
_buildIndex,
app,
indexNodeKey
)
2019-07-15 08:12:52 +02:00
const _buildIndex = async (app, indexNodeKey) => {
const indexNode = getNode(app.hierarchy, indexNodeKey)
2019-07-15 08:12:52 +02:00
await createBuildIndexFolder(app.datastore, indexNodeKey)
2019-07-15 08:12:52 +02:00
if (!isIndex(indexNode)) {
throw new BadRequestError("BuildIndex: must supply an indexnode")
}
2019-07-15 08:12:52 +02:00
if (indexNode.indexType === "reference") {
await buildReverseReferenceIndex(app, indexNode)
2019-07-15 08:12:52 +02:00
} else {
await buildHeirarchalIndex(app, indexNode)
2019-07-15 08:12:52 +02:00
}
await app.cleanupTransactions()
}
2019-07-15 08:12:52 +02:00
const buildReverseReferenceIndex = async (app, indexNode) => {
// Iterate through all referencING records,
// and update referenced index for each record
let recordCount = 0
2019-07-15 08:12:52 +02:00
const referencingNodes = $(app.hierarchy, [
getFlattenedHierarchy,
filter(
n =>
isRecord(n) && some(fieldReversesReferenceToIndex(indexNode))(n.fields)
),
])
2019-07-15 08:12:52 +02:00
const createTransactionsForReferencingNode = async referencingNode => {
const iterateReferencingNodes = await getAllIdsIterator(app)(
referencingNode.collectionNodeKey()
)
2019-07-15 08:12:52 +02:00
let referencingIdIterator = await iterateReferencingNodes()
2019-07-15 08:12:52 +02:00
while (!referencingIdIterator.done) {
const { result } = referencingIdIterator
2019-07-15 08:12:52 +02:00
for (const id of result.ids) {
const recordKey = joinKey(result.collectionKey, id)
await transactionForBuildIndex(
app,
indexNode.nodeKey(),
recordKey,
recordCount
)
recordCount++
2019-07-15 08:12:52 +02:00
}
referencingIdIterator = await iterateReferencingNodes()
2019-07-15 08:12:52 +02:00
}
}
2019-07-15 08:12:52 +02:00
for (const referencingNode of referencingNodes) {
await createTransactionsForReferencingNode(referencingNode)
2019-07-15 08:12:52 +02:00
}
}
2019-07-15 08:12:52 +02:00
/*
2019-07-15 08:12:52 +02:00
const getAllowedParentCollectionNodes = (hierarchy, indexNode) => $(getAllowedRecordNodesForIndex(hierarchy, indexNode), [
map(n => n.parent()),
]);
*/
2019-07-15 08:12:52 +02:00
const buildHeirarchalIndex = async (app, indexNode) => {
let recordCount = 0
2019-07-15 08:12:52 +02:00
const createTransactionsForIds = async (collectionKey, ids) => {
for (const recordId of ids) {
const recordKey = joinKey(collectionKey, recordId)
2019-07-15 08:12:52 +02:00
const recordNode = getRecordNodeById(app.hierarchy, recordId)
2019-07-15 08:12:52 +02:00
if (recordNodeApplies(indexNode)(recordNode)) {
await transactionForBuildIndex(
app,
indexNode.nodeKey(),
recordKey,
recordCount
)
recordCount++
2019-07-15 08:12:52 +02:00
}
}
}
2019-07-15 08:12:52 +02:00
const collectionRecords = getAllowedRecordNodesForIndex(
app.hierarchy,
indexNode
)
2019-07-15 08:12:52 +02:00
for (const targetCollectionRecordNode of collectionRecords) {
const allIdsIterator = await getAllIdsIterator(app)(
targetCollectionRecordNode.collectionNodeKey()
)
2019-07-15 08:12:52 +02:00
let allIds = await allIdsIterator()
2019-07-15 08:12:52 +02:00
while (allIds.done === false) {
await createTransactionsForIds(
allIds.result.collectionKey,
allIds.result.ids
)
allIds = await allIdsIterator()
2019-07-15 08:12:52 +02:00
}
}
return recordCount
}
2019-07-15 08:12:52 +02:00
// const chooseChildRecordNodeByKey = (collectionNode, recordId) => find(c => recordId.startsWith(c.nodeId))(collectionNode.children);
2019-07-15 08:12:52 +02:00
const recordNodeApplies = indexNode => recordNode =>
includes(recordNode.nodeId)(indexNode.allowedRecordNodeIds)
2019-07-15 08:12:52 +02:00
/*
2019-07-15 08:12:52 +02:00
const hasApplicableDecendant = (hierarchy, ancestorNode, indexNode) => $(hierarchy, [
getFlattenedHierarchy,
filter(
allTrue(
isRecord,
isDecendant(ancestorNode),
recordNodeApplies(indexNode),
),
),
]);
*/
2019-07-15 08:12:52 +02:00
/*
2019-07-15 08:12:52 +02:00
const applyAllDecendantRecords = async (app, collection_Key_or_NodeKey,
indexNode, indexKey, currentIndexedData,
currentIndexedDataKey, recordCount = 0) => {
const collectionNode = getCollectionNodeByKeyOrNodeKey(
app.hierarchy,
collection_Key_or_NodeKey,
);
const allIdsIterator = await getAllIdsIterator(app)(collection_Key_or_NodeKey);
const createTransactionsForIds = async (collectionKey, allIds) => {
for (const recordId of allIds) {
const recordKey = joinKey(collectionKey, recordId);
const recordNode = chooseChildRecordNodeByKey(
collectionNode,
recordId,
);
if (recordNodeApplies(indexNode)(recordNode)) {
await transactionForBuildIndex(
app, indexNode.nodeKey(),
recordKey, recordCount,
);
recordCount++;
}
if (hasApplicableDecendant(app.hierarchy, recordNode, indexNode)) {
for (const childCollectionNode of recordNode.children) {
recordCount = await applyAllDecendantRecords(
app,
joinKey(recordKey, childCollectionNode.collectionName),
indexNode, indexKey, currentIndexedData,
currentIndexedDataKey, recordCount,
);
}
}
}
};
let allIds = await allIdsIterator();
while (allIds.done === false) {
await createTransactionsForIds(
allIds.result.collectionKey,
allIds.result.ids,
);
allIds = await allIdsIterator();
}
return recordCount;
};
*/
2019-07-15 08:12:52 +02:00
export default buildIndex