Skip to content

mongoose plugin for tree hierarchy using the materialized path strategy

Notifications You must be signed in to change notification settings

sleede/mongoose-path-tree

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mongoose-path-tree

Build Status

Code Climate Test Coverage Issue Count

Dependency Status devDependency Status

Implements the materialized path strategy with cascade child re-parenting on delete for storing a hierarchy of documents with mongoose Version with all collected features and fixes from mongoose-tree, mongoose-tree-fix, mongoose-tree2, mongoose-reparenting-tree

Usage

Install via NPM

$ npm install mongoose-path-tree

Options

Model.plugin(tree, {
  pathSeparator : '#',              // Path separator. Default: '#'
  onDelete :      'REPARENT',       // Can be set to 'DELETE' or 'REPARENT'. Default: 'DELETE'
  numWorkers:     5,                // Number of stream workers. Default: 5
  idType:         Schema.ObjectId   // Type used for _id. Default: This Model Schema's _id type
})

Then you can use the plugin on your schemas

var tree = require('mongoose-path-tree');

var UserSchema = new Schema({
  name : String
});
UserSchema.plugin(tree);
var User = mongoose.model('User', UserSchema);

var adam = new User({ name : 'Adam' });
var bob = new User({ name : 'Bob' });
var carol = new User({ name : 'Carol' });

// Set the parent relationships
bob.parent = adam;
carol.parent = bob;

adam.save(function() {
  bob.save(function() {
    carol.save();
  });
});

At this point in mongoDB you will have documents similar to

    {
      "_id" : ObjectId("50136e40c78c4b9403000001"),
      "name" : "Adam",
      "path" : "50136e40c78c4b9403000001"
    }
    {
      "_id" : ObjectId("50136e40c78c4b9403000002"),
      "name" : "Bob",
      "parent" : ObjectId("50136e40c78c4b9403000001"),
      "path" : "50136e40c78c4b9403000001#50136e40c78c4b9403000002"
    }
    {
      "_id" : ObjectId("50136e40c78c4b9403000003"),
      "name" : "Carol",
      "parent" : ObjectId("50136e40c78c4b9403000002"),
      "path" : "50136e40c78c4b9403000001#50136e40c78c4b9403000002#50136e40c78c4b9403000003"
    }

The path is used for recursive methods and is kept up to date by the plugin if the parent is changed

API

getChildren

Signature:

doc.getChildren([filters], [fields], [options], [recursive], cb);

args are additional filters if needed. if recursive is supplied and true, subchildren are returned

Based on the above hierarchy:

adam.getChildren(function(err, users) {
  // users is an array of with the bob document
});

adam.getChildren(true, function(err, users) {
  // users is an array with both bob and carol documents
});

getChildrenTree

Signature as a method:

doc.getChildrenTree([args], cb);

Signature as a static:

Model.getChildrenTree([rootDoc], [args], cb);

returns (Object): recursive tree of sub-children.

args is an object you can defined with theses properties :

  • filters: Object, mongoose query filter, optional, default: {}
  • fields: String|Object, mongoose fields, optional, default: null (all fields)
  • options: Object, mongoose query option, optional, default: {}
  • minLevel: Number, level at which will start the search, default: 1
  • recursive: Boolean, make the search recursive or only fetch children for the specified level, default: true
  • allowEmptyChildren: Boolean, if true, every child not having children would still have children attribute (an empty array), if false, every child not having children will have children attribute at all, default: true
  • objectify: Boolean|Object, wheather to run toObject() method on every child, can be either Boolean or an toObject() options Object, default: false
  • populationQuery: String, populate fields, default: ''

Example :

var args = {
  filters: {owner:myId},
  fields: "_id name owner",
  minLevel:2,
  recursive:true,
  allowEmptyChildren:false
}

getChildrenTree(args,myCallback);

Based on the above hierarchy:

adam.getChildrenTree( function(err, users) {

    /* if you dump users, you will have something like this :
    {
      "_id" : ObjectId("50136e40c78c4b9403000001"),
      "name" : "Adam",
      "path" : "50136e40c78c4b9403000001"
      "children" : [{
          "_id" : ObjectId("50136e40c78c4b9403000002"),
          "name" : "Bob",
          "parent" : ObjectId("50136e40c78c4b9403000001"),
          "path" : "50136e40c78c4b9403000001#50136e40c78c4b9403000002"
          "children" : [{
              "_id" : ObjectId("50136e40c78c4b9403000003"),
              "name" : "Carol",
              "parent" : ObjectId("50136e40c78c4b9403000002"),
              "path" : "50136e40c78c4b9403000001#50136e40c78c4b9403000002#50136e40c78c4b9403000003"
          }]
      }]
    }
    */

});

getAncestors

Signature:

doc.getAncestors([filters], [fields], [options], cb);

Based on the above hierarchy:

carol.getAncestors(function(err, users) {
  // users as an array [adam, bob] (older -> younger)
})

level

Virtual property (Number, strating at 1), equals to the level in the hierarchy

carol.level; // equals 3

Tests

To run the tests install mocha

npm install mocha -g

and then run

mocha

About

mongoose plugin for tree hierarchy using the materialized path strategy

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%