Michal Majernik Michal Majernik - 2 months ago 74
Node.js Question

mongoose recursive populate

I have been searching for a while and I didn't find any good answer. I have n-deep tree that I am storing in DB and I would like to populate all parents so in the end I get the full tree

node
-parent
-parent
.
.
-parent


So far I populate to level 2, and as I mentioned I need to get to level n.

Node.find().populate('parent').exec(function (err, items) {
if (!err) {
Node.populate(items, {path: 'parent.parent'}, function (err, data) {
return res.send(data);
});
} else {
res.statusCode = code;
return res.send(err.message);
}
});

Answer

Just don't :)

There is no good way to do that. Even if you do some map-reduce, it will have terrible performance and problems with sharding if you have it or will ever need it.

Mongo as NoSQL database is really great for storing tree documents. You can store whole tree and then use map-reduce to get some particular leafs from it if you don't have a lot of "find particular leaf" queries. If this doesn't work for you, go with two collections:

  1. Simplified tree structure: {_id: "tree1", tree: {1: [2, {3: [4, {5: 6}, 7]}]}}. Numbers are just IDs of nodes. This way you'll get whole document in one query. Then you just extract all ids and run second query.

  2. Nodes: {_id: 1, data: "something"}, {_id: 2, data: "something else"}.

Then you can write simple recurring function which will replace node ids from first collection with data from second. 2 queries and simple client-side processing.

Small update:

You can extend second collection to be a little more flexible:

{_id: 2, data: "something", children:[3, 7], parents: [1, 12, 13]}

This way you'll be able to start your search from any leaf. And then, use map-reduce to get to the top or to the bottom of this part of tree.