Began migration of queries to nested sets

This commit is contained in:
Thaum Rystra
2023-10-03 16:28:20 +02:00
parent 28a19f2037
commit f63d2ad254
41 changed files with 242 additions and 392 deletions

View File

@@ -7,6 +7,7 @@ import { assertEditPermission, assertOwnership } from '/imports/api/sharing/shar
import LibraryNodes from '/imports/api/library/LibraryNodes';
import { getUserTier } from '/imports/api/users/patreon/tiers'
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
import { getFilter } from '/imports/api/parenting/parentingFunctions';
/**
* Libraries are trees of library nodes where each node represents a character
@@ -160,7 +161,7 @@ const removeLibrary = new ValidatedMethod({
export function removeLibaryWork(libraryId) {
Libraries.remove(libraryId);
LibraryNodes.remove({ 'ancestors.id': libraryId });
LibraryNodes.remove(getFilter.descendantsOfRoot(libraryId));
}
export { LibrarySchema, insertLibrary, updateLibraryName, updateLibraryDescription, updateLibraryShowInMarket, removeLibrary };

View File

@@ -15,7 +15,7 @@ import '/imports/api/library/methods/index';
import { updateReferenceNodeWork } from '/imports/api/library/methods/updateReferenceNode';
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
import { restore } from '/imports/api/parenting/softRemove';
import { getAncestry } from '/imports/api/parenting/parentingFunctions';
import { fetchDocByRef, getAncestry } from '/imports/api/parenting/parentingFunctions';
import { rebuildNestedSets } from '/imports/api/parenting/parentingFunctions';
let LibraryNodes = new Mongo.Collection('libraryNodes');
@@ -122,7 +122,7 @@ for (let key in propertySchemasIndex) {
function getLibrary(node) {
if (!node) throw new Meteor.Error('No node provided');
let library = Libraries.findOne(node.ancestors[0].id);
let library = Libraries.findOne(node.root.id);
if (!library) throw new Meteor.Error('Library does not exist');
return library;
}
@@ -148,22 +148,20 @@ const insertNode = new ValidatedMethod({
},
run({ libraryNode, parentRef }) {
// get the new ancestry
let { parentDoc, ancestors } = getAncestry({ parentRef });
const parentDoc = fetchDocByRef(parentRef);
// Check permission to edit
let root;
if (parentRef.collection === 'libraries') {
root = parentDoc;
} else if (parentRef.collection === 'libraryNodes') {
root = Libraries.findOne(parentDoc.ancestors[0].id);
root = Libraries.findOne(parentDoc.root.id);
libraryNode.parentId = parentRef.id;
} else {
throw `${parentRef.collection} is not a valid parent collection`
}
assertEditPermission(root, this.userId);
// Set the ancestry of the library node
libraryNode.parent = parentRef;
libraryNode.ancestors = ancestors;
// Remove its ID if it came with one to force a random one to be generated
// server-side
delete libraryNode._id;
@@ -195,6 +193,8 @@ const updateLibraryNode = new ValidatedMethod({
case 'order':
case 'parent':
case 'ancestors':
case 'parentId':
case 'root':
return false;
}
},
@@ -296,7 +296,7 @@ const restoreLibraryNode = new ValidatedMethod({
let node = LibraryNodes.findOne(_id);
assertNodeEditPermission(node, this.userId);
// Do work
restore({ _id, collection: LibraryNodes });
restore(LibraryNodes, _id);
}
});

View File

@@ -9,7 +9,8 @@ import {
} from '/imports/api/sharing/sharingPermissions';
import {
setLineageOfDocs,
renewDocIds
renewDocIds,
getFilter
} from '/imports/api/parenting/parentingFunctions';
import { rebuildNestedSets } from '/imports/api/parenting/parentingFunctions';
import { fetchDocByRef } from '/imports/api/parenting/parentingFunctions';
@@ -46,12 +47,14 @@ const copyLibraryNodeTo = new ValidatedMethod({
);
}
const libraryNode = LibraryNodes.findOne(_id);
if (!libraryNode) throw new Meteor.Error('not-found', 'Library node was not found');
const parentDoc = fetchDocByRef(parent);
assertDocCopyPermission(libraryNode, this.userId);
assertDocEditPermission(parentDoc, this.userId);
let decendants = LibraryNodes.find({
'ancestors.id': _id,
...getFilter.descendants(libraryNode),
removed: { $ne: true },
}, {
limit: DUPLICATE_CHILDREN_LIMIT + 1,
@@ -69,26 +72,16 @@ const copyLibraryNodeTo = new ValidatedMethod({
const nodes = [libraryNode, ...decendants];
const newAncestry = parentDoc.ancestors || [];
newAncestry.push(parent);
// re-map all the ancestors
setLineageOfDocs({
docArray: nodes,
newAncestry,
oldParent: libraryNode.parent,
});
// Give the docs new IDs without breaking internal references
renewDocIds({ docArray: nodes });
// Order the root node
libraryNode.order = (parentDoc.order || 0) + 0.5;
libraryNode.left = Number.MAX_SAFE_INTEGER - 1;
libraryNode.right = Number.MAX_SAFE_INTEGER;
LibraryNodes.batchInsert(nodes);
// Tree structure changed by inserts, reorder the tree
// TODO: rebuild tree nested sets
rebuildNestedSets(LibraryNodes, parentDoc.root.id);
},
});

View File

@@ -5,7 +5,8 @@ import LibraryNodes from '/imports/api/library/LibraryNodes';
import { assertDocEditPermission } from '/imports/api/sharing/sharingPermissions';
import {
setLineageOfDocs,
renewDocIds
renewDocIds,
getFilter
} from '/imports/api/parenting/parentingFunctions';
import { rebuildNestedSets } from '/imports/api/parenting/parentingFunctions';
@@ -33,6 +34,8 @@ const duplicateLibraryNode = new ValidatedMethod({
},
run({ _id }) {
let libraryNode = LibraryNodes.findOne(_id);
if (!libraryNode) throw new Meteor.Error('not-found', 'Library node was not found');
assertDocEditPermission(libraryNode, this.userId);
let randomSrc = DDP.randomStream('duplicateLibraryNode');
@@ -40,7 +43,7 @@ const duplicateLibraryNode = new ValidatedMethod({
libraryNode._id = libraryNodeId;
let nodes = LibraryNodes.find({
'ancestors.id': _id,
...getFilter.descendants(libraryNode),
removed: { $ne: true },
}, {
limit: DUPLICATE_CHILDREN_LIMIT + 1,
@@ -56,16 +59,6 @@ const duplicateLibraryNode = new ValidatedMethod({
}
}
// re-map all the ancestors
setLineageOfDocs({
docArray: nodes,
newAncestry: [
...libraryNode.ancestors,
{ id: libraryNodeId, collection: 'libraryNodes' }
],
oldParent: { id: _id, collection: 'libraryNodes' },
});
// Give the docs new IDs without breaking internal references
const allNodes = [libraryNode, ...nodes];
renewDocIds({ docArray: allNodes });
@@ -76,10 +69,7 @@ const duplicateLibraryNode = new ValidatedMethod({
LibraryNodes.batchInsert(allNodes);
// Tree structure changed by inserts, reorder the tree
reorderDocs({
collection: LibraryNodes,
ancestorId: libraryNode.ancestors[0].id,
});
rebuildNestedSets(LibraryNodes, libraryNode.root.id);
return libraryNodeId;
},

View File

@@ -11,8 +11,8 @@ export default function getDefaultSlotFiller(slot) {
type: slotType,
libraryTags: slot.slotTags || [],
name: 'Custom ' + slot.name || 'slot filler',
parent: { collection: 'creatureProperties', id: slot._id },
ancestors: [...slot.ancestors, { collection: 'creatureProperties', id: slot._id }],
parentId: slot._id,
root: { ...slot.root },
};
return filler;
}

View File

@@ -45,8 +45,8 @@ function updateReferenceNodeWork(node, userId) {
try {
doc = fetchDocByRef(node.ref);
if (doc.removed) throw 'Property has been deleted';
if (doc.ancestors[0].id !== node.ancestors[0].id) {
library = fetchDocByRef(doc.ancestors[0]);
if (doc.root.id !== node.root.id) {
library = fetchDocByRef(doc.root);
assertViewPermission(library, userId)
}
} catch (e) {