2019-07-15 08:12:52 +02:00
|
|
|
import {
|
2019-12-22 08:12:21 +01:00
|
|
|
filter,
|
2019-07-15 08:12:52 +02:00
|
|
|
includes, some,
|
|
|
|
} from 'lodash/fp';
|
|
|
|
import { getAllIdsIterator } from '../indexing/allIds';
|
|
|
|
import {
|
|
|
|
getFlattenedHierarchy, getRecordNodeById,
|
2019-12-22 08:12:21 +01:00
|
|
|
getNode, isIndex,
|
|
|
|
isRecord, getAllowedRecordNodesForIndex,
|
2019-07-15 08:12:52 +02:00
|
|
|
fieldReversesReferenceToIndex,
|
|
|
|
} from '../templateApi/hierarchy';
|
|
|
|
import {
|
2019-12-22 08:12:21 +01:00
|
|
|
joinKey, apiWrapper, events, $
|
2019-07-15 08:12:52 +02:00
|
|
|
} from '../common';
|
|
|
|
import {
|
|
|
|
createBuildIndexFolder,
|
|
|
|
transactionForBuildIndex,
|
|
|
|
} from '../transactions/create';
|
|
|
|
import { permission } from '../authApi/permissions';
|
|
|
|
import { BadRequestError } from '../common/errors';
|
|
|
|
|
|
|
|
|
|
|
|
/** 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,
|
|
|
|
);
|
|
|
|
|
|
|
|
const _buildIndex = async (app, indexNodeKey) => {
|
|
|
|
const indexNode = getNode(app.hierarchy, indexNodeKey);
|
|
|
|
|
|
|
|
await createBuildIndexFolder(app.datastore, indexNodeKey);
|
|
|
|
|
|
|
|
if (!isIndex(indexNode)) { throw new BadRequestError('BuildIndex: must supply an indexnode'); }
|
|
|
|
|
|
|
|
if (indexNode.indexType === 'reference') {
|
|
|
|
await buildReverseReferenceIndex(
|
|
|
|
app, indexNode,
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
await buildHeirarchalIndex(
|
|
|
|
app, indexNode,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
await app.cleanupTransactions();
|
|
|
|
};
|
|
|
|
|
|
|
|
const buildReverseReferenceIndex = async (app, indexNode) => {
|
|
|
|
// Iterate through all referencING records,
|
|
|
|
// and update referenced index for each record
|
|
|
|
let recordCount = 0;
|
|
|
|
const referencingNodes = $(app.hierarchy, [
|
|
|
|
getFlattenedHierarchy,
|
|
|
|
filter(n => isRecord(n)
|
|
|
|
&& some(fieldReversesReferenceToIndex(indexNode))(n.fields)),
|
|
|
|
]);
|
|
|
|
|
|
|
|
const createTransactionsForReferencingNode = async (referencingNode) => {
|
|
|
|
const iterateReferencingNodes = await getAllIdsIterator(app)(referencingNode.collectionNodeKey());
|
|
|
|
|
|
|
|
let referencingIdIterator = await iterateReferencingNodes();
|
|
|
|
while (!referencingIdIterator.done) {
|
|
|
|
const { result } = referencingIdIterator;
|
|
|
|
for (const id of result.ids) {
|
|
|
|
const recordKey = joinKey(result.collectionKey, id);
|
|
|
|
await transactionForBuildIndex(app, indexNode.nodeKey(), recordKey, recordCount);
|
|
|
|
recordCount++;
|
|
|
|
}
|
|
|
|
referencingIdIterator = await iterateReferencingNodes();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const referencingNode of referencingNodes) {
|
|
|
|
await createTransactionsForReferencingNode(referencingNode);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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) => {
|
|
|
|
let recordCount = 0;
|
|
|
|
|
|
|
|
const createTransactionsForIds = async (collectionKey, ids) => {
|
|
|
|
for (const recordId of ids) {
|
|
|
|
const recordKey = joinKey(collectionKey, recordId);
|
|
|
|
|
|
|
|
const recordNode = getRecordNodeById(
|
|
|
|
app.hierarchy,
|
|
|
|
recordId,
|
|
|
|
);
|
|
|
|
|
|
|
|
if (recordNodeApplies(indexNode)(recordNode)) {
|
|
|
|
await transactionForBuildIndex(
|
|
|
|
app, indexNode.nodeKey(),
|
|
|
|
recordKey, recordCount,
|
|
|
|
);
|
|
|
|
recordCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const collectionRecords = getAllowedRecordNodesForIndex(app.hierarchy, indexNode);
|
|
|
|
|
|
|
|
for (const targetCollectionRecordNode of collectionRecords) {
|
|
|
|
const allIdsIterator = await getAllIdsIterator(app)(targetCollectionRecordNode.collectionNodeKey());
|
|
|
|
|
|
|
|
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
|
|
|
// 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-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
|
|
|
|
2019-12-22 08:12:21 +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
|
|
|
|
|
|
|
export default buildIndex;
|