Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose.js: How to Implement Tree Structure via Population

I'm working on implementing a tree structure (similar to this one in the Mongo docs) using Mongoose 3.x, but I'm unsure of the best way to encapsulate all the logic for loading a specific node with its siblings and ancestors generally, and specifically how to best work with the population functionality where the ref is in the same collection as the ref-er.

For some context, the tree I'm working with is one in which nodes are not edited but new children might be added at any time to any node. So far I've got this working fine with a set of model methods that load objects after the initial find, but it seems there should be a better way to easily load a single branch with all the parent and sibling data I need with a single command in the controller, and encapsulate all the relevant population in some convenient find method on the model.

The basic Schema I'm trying to work with, then, might be something like this (also available here: https://gist.github.com/3889616):

// Sub-document to store parent ref along with it's value (a form of caching)
var Parent = new Schema({
    id: ObjectId
  , text: String
});

// Main tree-node element schema
var Branch = new Schema({
    text: {
        type: String
      , required: true }
  , date: {type: Date, default: Date.now }
  , trail: [Parent]
  , parentBranchId: ObjectId
  , parentBranch: { type: Schema.Types.ObjectId, ref: 'Branch' }
  , _children: [{type: Schema.Types.ObjectId, ref: 'Branch'}]
  // These two have been commented out because I have no clue how to best implement 
  // , _priorSiblings: { type: Schema.Types.ObjectId, ref: 'Branch' }
  // , _followingSiblings: { type: Schema.Types.ObjectId, ref: 'Branch' }
});

My hope would then be to be able to load a branch w/ the relevant related data via something like the following code, though at this point I'm pretty much lost and could be a good deal off base:

  req.app.models.Branch
    .findById(req.param("id"))
    .populate("parentBranch")
    .populate("parentBranch._children")
    .exec(...)

Ultimately, I'd love to have something I could abstract into a "tree" plugin for Mongoose, but I think I've got to get this architected correctly first. Any ideas?

FWIW, at the end of the day, the data I really need for each branch is parent, next sibling, previous sibling (both in terms of creation time) and all children of parent.

Thanks in advance!

like image 954
Ethan Winn Avatar asked Oct 15 '12 01:10

Ethan Winn


1 Answers

I know this question is old, but have you looked into the mongoose-tree module? https://github.com/franck34/mongoose-tree

It has a pretty good API for handling relationships between objects IMO.

like image 163
call_de_amberlamps Avatar answered Sep 20 '22 14:09

call_de_amberlamps