Fixed more failing tests to match nested sets
This commit is contained in:
@@ -74,6 +74,25 @@ describe('Parenting with nested sets', function () {
|
||||
op('dbm', 8, 9),
|
||||
]);
|
||||
});
|
||||
it('Can recalculate left and right for docs with set parents in random order', function () {
|
||||
const docArray = [
|
||||
doc('MongoDB', 71, 33, 'Databases'),
|
||||
doc('Programming', 72, 33, 'Books'),
|
||||
doc('Languages', 73, 33, 'Programming'),
|
||||
doc('Books', 74, 33, undefined),
|
||||
doc('Databases', 75, 33, 'Programming'),
|
||||
doc('dbm', 76, 33, 'Databases'),
|
||||
];
|
||||
const ops = calculateNestedSetOperations(docArray);
|
||||
assert.deepEqual(ops, [
|
||||
op('Books', 1, 12),
|
||||
op('Programming', 2, 11),
|
||||
op('Languages', 3, 4),
|
||||
op('Databases', 5, 10),
|
||||
op('MongoDB', 6, 7),
|
||||
op('dbm', 8, 9),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Document tree filters can fetch other documents based on their position in the tree', function () {
|
||||
|
||||
@@ -381,18 +381,23 @@ export async function rebuildNestedSets(collection: Mongo.Collection<TreeDoc>, r
|
||||
await writeBulkOperations(collection, operations);
|
||||
}
|
||||
|
||||
/** Calculates the operations needed to make a tree of nested sets
|
||||
* Warning: Will reverse the order of docs!
|
||||
* Walk around the tree numbering left on the way down and right on the way up like so:
|
||||
*
|
||||
* 1 Books 12
|
||||
* ┃
|
||||
* 2 Programming 11
|
||||
* ┏━━━━━━━━┻━━━━━━━━━┓
|
||||
* 3 Languages 4 5 Databases 10
|
||||
* ┏━━━━━━━┻━━━━━━━┓
|
||||
* 6 MongoDB 7 8 dbm 9
|
||||
*
|
||||
*
|
||||
* @param docs
|
||||
* @returns
|
||||
*/
|
||||
export function calculateNestedSetOperations(docs: TreeDoc[]) {
|
||||
// Walk around the tree numbering left on the way down and right on the way up like so:
|
||||
/*
|
||||
* 1 Books 12
|
||||
* ┃
|
||||
* 2 Programming 11
|
||||
* ┏━━━━━━━━┻━━━━━━━━━┓
|
||||
* 3 Languages 4 5 Databases 10
|
||||
* ┏━━━━━━━┻━━━━━━━┓
|
||||
* 6 MongoDB 7 8 dbm 9
|
||||
*/
|
||||
// Get the forest, but in reverse order so that the stack always has the first documents on top
|
||||
const { forest: stack, orphanIds } = docsToForestByParentId(reverse(docs));
|
||||
const removeMissingParentsOp = orphanIds.length ? {
|
||||
updateMany: {
|
||||
@@ -442,6 +447,51 @@ export function calculateNestedSetOperations(docs: TreeDoc[]) {
|
||||
return operations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as calculateNestedSetOperations, but applies the ops to the properties
|
||||
* Mostly used to create testing documents.
|
||||
* @param docs
|
||||
* @returns
|
||||
*/
|
||||
export function applyNestedSetProperties(docs: TreeDoc[]) {
|
||||
// Walk around the tree numbering left on the way down and right on the way up like so:
|
||||
const { forest: stack, orphanIds } = docsToForestByParentId(reverse([...docs]));
|
||||
|
||||
const visitedNodes = new Set();
|
||||
const visitedChildren = new Set();
|
||||
let count = 1;
|
||||
|
||||
while (stack.length) {
|
||||
const top = stack[stack.length - 1];
|
||||
if (orphanIds.includes(top.doc._id)) {
|
||||
delete top.doc.parentId;
|
||||
}
|
||||
if (visitedNodes.has(top)) {
|
||||
// We've arrived at this node again for some reason, this shouldn't happen
|
||||
console.log('visited already, parent loop maybe?')
|
||||
stack.pop();
|
||||
} else if (visitedChildren.has(top)) {
|
||||
// We've arrived at this node after visiting the children,
|
||||
// we must be on the way up, mark the right number
|
||||
visitedNodes.add(top);
|
||||
stack.pop();
|
||||
if (top.doc.right !== count) {
|
||||
top.doc.right = count;
|
||||
}
|
||||
count += 1;
|
||||
} else {
|
||||
// We're arriving at this node for the first time
|
||||
// We must be on the way down, mark the left number and go visit the children
|
||||
visitedChildren.add(top);
|
||||
stack.push(...top.children);
|
||||
if (top.doc.left !== count) {
|
||||
top.doc.left = count;
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write some number of bulk operations to the collection, uses a bulk write on the server
|
||||
* and iterates through regular updates on the client
|
||||
|
||||
Reference in New Issue
Block a user