2020-02-03 10:24:25 +01:00
|
|
|
import { filter, includes, some } from "lodash/fp"
|
|
|
|
import { getAllIdsIterator } from "../indexing/allIds"
|
2019-07-15 08:12:52 +02:00
|
|
|
import {
|
2020-02-03 10:24:25 +01:00
|
|
|
getFlattenedHierarchy,
|
|
|
|
getRecordNodeById,
|
|
|
|
getNode,
|
|
|
|
isIndex,
|
|
|
|
isRecord,
|
|
|
|
getAllowedRecordNodesForIndex,
|
2019-07-15 08:12:52 +02:00
|
|
|
fieldReversesReferenceToIndex,
|
2020-02-03 10:24:25 +01:00
|
|
|
} from "../templateApi/hierarchy"
|
|
|
|
import { joinKey, apiWrapper, events, $ } from "../common"
|
2019-07-15 08:12:52 +02:00
|
|
|
import {
|
|
|
|
createBuildIndexFolder,
|
|
|
|
transactionForBuildIndex,
|
2020-02-03 10:24:25 +01:00
|
|
|
} 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
|
|
|
|
*/
|
2020-02-03 10:24:25 +01:00
|
|
|
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) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
const indexNode = getNode(app.hierarchy, indexNodeKey)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
await createBuildIndexFolder(app.datastore, indexNodeKey)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (!isIndex(indexNode)) {
|
|
|
|
throw new BadRequestError("BuildIndex: must supply an indexnode")
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
if (indexNode.indexType === "reference") {
|
|
|
|
await buildReverseReferenceIndex(app, indexNode)
|
2019-07-15 08:12:52 +02:00
|
|
|
} else {
|
2020-02-03 10:24:25 +01:00
|
|
|
await buildHeirarchalIndex(app, indexNode)
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
|
2020-02-03 10:24:25 +01: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
|
2020-02-03 10:24:25 +01:00
|
|
|
let recordCount = 0
|
2019-07-15 08:12:52 +02:00
|
|
|
const referencingNodes = $(app.hierarchy, [
|
|
|
|
getFlattenedHierarchy,
|
2020-02-03 10:24:25 +01:00
|
|
|
filter(
|
|
|
|
n =>
|
|
|
|
isRecord(n) && some(fieldReversesReferenceToIndex(indexNode))(n.fields)
|
|
|
|
),
|
|
|
|
])
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const createTransactionsForReferencingNode = async referencingNode => {
|
|
|
|
const iterateReferencingNodes = await getAllIdsIterator(app)(
|
|
|
|
referencingNode.collectionNodeKey()
|
|
|
|
)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
let referencingIdIterator = await iterateReferencingNodes()
|
2019-07-15 08:12:52 +02:00
|
|
|
while (!referencingIdIterator.done) {
|
2020-02-03 10:24:25 +01:00
|
|
|
const { result } = referencingIdIterator
|
2019-07-15 08:12:52 +02:00
|
|
|
for (const id of result.ids) {
|
2020-02-03 10:24:25 +01:00
|
|
|
const recordKey = joinKey(result.collectionKey, id)
|
|
|
|
await transactionForBuildIndex(
|
|
|
|
app,
|
|
|
|
indexNode.nodeKey(),
|
|
|
|
recordKey,
|
|
|
|
recordCount
|
|
|
|
)
|
|
|
|
recordCount++
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
2020-02-03 10:24:25 +01:00
|
|
|
referencingIdIterator = await iterateReferencingNodes()
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
2020-02-03 10:24:25 +01:00
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
for (const referencingNode of referencingNodes) {
|
2020-02-03 10:24:25 +01:00
|
|
|
await createTransactionsForReferencingNode(referencingNode)
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
2020-02-03 10:24:25 +01:00
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2019-12-22 08:12:21 +01:00
|
|
|
/*
|
2019-07-15 08:12:52 +02:00
|
|
|
const getAllowedParentCollectionNodes = (hierarchy, indexNode) => $(getAllowedRecordNodesForIndex(hierarchy, indexNode), [
|
|
|
|
map(n => n.parent()),
|
|
|
|
]);
|
2019-12-22 08:12:21 +01:00
|
|
|
*/
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
const buildHeirarchalIndex = async (app, indexNode) => {
|
2020-02-03 10:24:25 +01:00
|
|
|
let recordCount = 0
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
const createTransactionsForIds = async (collectionKey, ids) => {
|
|
|
|
for (const recordId of ids) {
|
2020-02-03 10:24:25 +01:00
|
|
|
const recordKey = joinKey(collectionKey, recordId)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const recordNode = getRecordNodeById(app.hierarchy, recordId)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
if (recordNodeApplies(indexNode)(recordNode)) {
|
|
|
|
await transactionForBuildIndex(
|
2020-02-03 10:24:25 +01:00
|
|
|
app,
|
|
|
|
indexNode.nodeKey(),
|
|
|
|
recordKey,
|
|
|
|
recordCount
|
|
|
|
)
|
|
|
|
recordCount++
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
}
|
2020-02-03 10:24:25 +01:00
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const collectionRecords = getAllowedRecordNodesForIndex(
|
|
|
|
app.hierarchy,
|
|
|
|
indexNode
|
|
|
|
)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
|
|
|
for (const targetCollectionRecordNode of collectionRecords) {
|
2020-02-03 10:24:25 +01:00
|
|
|
const allIdsIterator = await getAllIdsIterator(app)(
|
|
|
|
targetCollectionRecordNode.collectionNodeKey()
|
|
|
|
)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
let allIds = await allIdsIterator()
|
2019-07-15 08:12:52 +02:00
|
|
|
while (allIds.done === false) {
|
|
|
|
await createTransactionsForIds(
|
|
|
|
allIds.result.collectionKey,
|
2020-02-03 10:24:25 +01:00
|
|
|
allIds.result.ids
|
|
|
|
)
|
|
|
|
allIds = await allIdsIterator()
|
2019-07-15 08:12:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
return recordCount
|
|
|
|
}
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2019-12-22 08:12:21 +01:00
|
|
|
// const chooseChildRecordNodeByKey = (collectionNode, recordId) => find(c => recordId.startsWith(c.nodeId))(collectionNode.children);
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
const recordNodeApplies = indexNode => recordNode =>
|
|
|
|
includes(recordNode.nodeId)(indexNode.allowedRecordNodeIds)
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2019-12-22 08:12:21 +01:00
|
|
|
/*
|
2019-07-15 08:12:52 +02:00
|
|
|
const hasApplicableDecendant = (hierarchy, ancestorNode, indexNode) => $(hierarchy, [
|
|
|
|
getFlattenedHierarchy,
|
|
|
|
filter(
|
|
|
|
allTrue(
|
|
|
|
isRecord,
|
|
|
|
isDecendant(ancestorNode),
|
|
|
|
recordNodeApplies(indexNode),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
]);
|
2019-12-22 08:12:21 +01:00
|
|
|
*/
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01: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-12-22 08:12:21 +01:00
|
|
|
*/
|
2019-07-15 08:12:52 +02:00
|
|
|
|
2020-02-03 10:24:25 +01:00
|
|
|
export default buildIndex
|