mongoose-materialized
v0.2.0
Published
Materialized path hierarchy for mongoose
Downloads
6,097
Maintainers
Readme
Mongoose Materialized
A mongoose plugin for the materialized paths.
Overview
Usage
var mongoose = require('mongoose'),
materializedPlugin = require('mongoose-materialized'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/materialized');
var CatSchema = new Schema({
name: {type: String}
});
CatSchema.plugin(materializedPlugin);
var Cat= mongoose.model('Cat', CatSchema); // Category
Examples
Adding root and child element.
Important: The model verifies the existence of the parent category before they would save. Except for the root element or change the parent id not touch.
// if you have predefined datas with parent id
Cat.Building(function(){
// building materialized path
});
// add root element
cat = new Cat({name: "Foods"});
cat.save(function(err, foods){
// append new sub category
foods.appendChild({name: "Vegetables"}, function(err, vega){
// vega: { name: "Vegetables", parentId: [foods ID], path: ',[foods ID]' }
});
// or make new
var vega = new Cat({name: "Vegetables"});
// saving with append
foods.appendChild(vega, function(err, data){ ... });
// or save traditional way
vega.parentId = foods._id;
vega.save(function(err, data){ ... });
});
Find element and checking the relationship
Cat.findOne({parentId: null}, function(err, doc){
// access to the children
doc.getChildren(function(err, docs){
// ...
});
// access to the children with condition and sort
doc.getChildren({
condition: { name: /^a/ },
sort: { name: 1 }
},function(err, docs){
// ...
});
// access to the siblings
doc.getSiblings(function(err, docs){
// ...
});
// access to the ancestors
doc.getAncestors(function(err, docs){
// ...
});
// check element is root
doc.isRoot(function(err, isOk){ ... });
// check element is leaf
doc.isLeaf(function(err, isLeaf){ ... });
// depth virtual attributes
doc.depth
// use promise
doc.getChildren().then(function(docs){
// ...
});
// get doc array tree
doc.getArrayTree(function(err, tree){
// ... [ {"_id": "...", "children": [ {...} ]}]
});
// get doc tree
doc.getTree(function(err, tree){
// ... { "doc ID": { ..., children: { ... } }
});
// or get tree with condition and sorting
doc.getTree({
condition: { name: /^[a-zA-Z]+$/ },
sort: { name: 1 }
}, function(err, tree){
// ...
});
});
Cat.GetTree('elemt ID', function (err, tree) {
// ...
});
Cat.GetArrayTree('elemt ID', function (err, tree) {
// ...
});
// access for full tree in array
Cat.GetFullArrayTree(function (err, tree) {
});
// access for full tree object
Cat.GetFullTree(function (err, tree) {
});
The different arrayTree and simple Tree methods: arrayTree result:
[
{ _id: 53ee2db76f2d838a07a04e6a,
path: '',
name: 'Foods',
__v: 0,
_w: 0,
parentId: null,
depth: 0,
id: '53ee2db76f2d838a07a04e6a',
children: [ [Object], [Object] ]
}
]
and the Tree result:
{ '53ee2db76f2d838a07a04e6a':
{ _id: 53ee2db76f2d838a07a04e6a,
path: '',
name: 'Foods',
__v: 0,
_w: 0,
parentId: null,
depth: 0,
id: '53ee2db76f2d838a07a04e6a',
children: {
'53ee2db76f2d838a07a04e6b': [Object]
}
}
}
Manipulate child element with static method mongoose-materialized it is possible to use more than one root.
Cat.AppendChild('ID', { 'name': 'Meats'}, function(err, doc){ ... });
Cat.getChildren('ID', function(err, childs){ ... });
Cat.getRoots(function(err, roots){
// root elements
});
// Format tree, sub element stored in children field
Cat.getRoots({ name: "" }).then(function (err, root) {
root.getChildren().then(function (err, children) {
console.log( Cat.toTree(children) );
// or only shown name
console.log( Cat.toTree(children, { name: 1 }) );
});
});
Hierarchical builder for the existing data. Important: This operation is relatively slow. Use only the conversion.
Cat.Building(function(){
// builded materialized path sturcture
});
// This example convert nested set to materialized path. Use this function to migration.
Cat.Building({
remove: { lt: 1, gt: 1, children: 1 } // remove nested fields from existsing data
}, function(){
// building is competted
});
API
Instructions
The following methods must be used with a callback. The callback method have two arguments. The first error and the second data object. If all goes well then the error is null.
model.calledFunction( function (error, data) {
if (error)
// handle error
});
The methods with work callback return promise. Mongoose Promise
model.calledFunction().then( function (data) {
}, function (err) {
// handle error
});
Imprtant! Do not use the following methods:
- Model.findByIdAndUpdate()
- Model.findByOneAndUpdate()
- Model.findByIdAndRemove()
- Model.findByOneAndRemove()
- Model.update() - static version
- instance.update()
- Model.remove() - static version
These functions are not triggered by the removal and saving events.
Instead, the following are recommended:
- instance.save() - saving and update (before use findOne, findById)
- instance.remove() - remove document (before use findOne, findById)
- Model.Remove(condition, callback)
The my query
object is special object for mongo query. This parameter available for functions.
var query = {
// mongo condition
condition: {
name: /^a/
},
// selected fields
fields: {
_id: 1,
name: 1
},
// sorting
sort: {
name: -1
}
};
// Example get chidls with query
doc.getChilds(query, function(err, docs){ ... });
To run the tests:
npm test
Attributes
Added attributes:
- parentId: Parent item id.
- path: materialized path. Auto generated
- _w: weight for sort
- depth: (virtual) element depth
Static methods
Similar method has the static begins with the first letter capitalized. (IsLeaft is static and isLeaf non static)
IsLeaf(ModelOrId, callback)
IsRoot(ModelOrId, callback)
GetChildren(ModelOrId, [query,] callback)
GetRoots([query,] callback)
GetTree(root condition, [children query,] callback) - get elemets tree with children
GetFullTree(callback)
GetArrayTree(root condition, [children query,] callback) - get elemets tree with children
GetFullArrayTree(callback)
Remove(condition, callback) - use this instead of remove.
AppendChild(ModelOrId, callback)
ToTree(documentArray, selected fields) Return object, no mongoose document (toObject()). Fields: { name: 1, _id: 1 }
ToArrayTree(documentArray, selected fields) Return objects in array, no mongoose document (toObject()). Fields: { name: 1, _id: 1 }
Building([prepare,] callback) - rebuild material path (good for extisting collections - parentId is needed)
Methods
isRoot(callback)
isLeaf(callback)
isDescendant(callback)
isParent(ModelOrId, callback)
isSibling(ModelOrID, callback)
getParent(callback)
getDescendants([query,] callback)
getChildren([query,] callback) alias for getDescendants
getAncestors([query,] callback)
getSiblings([query,] callback)
getTree([query,] callback) - get elemets tree with children
getArrayTree([query,] callback) - get elemets tree with children, array version
appendChild(model, callback)
setParent(ModelOrId) - if parameter is ID then check parent existence and set parentId (the model parameter to avoid the query)
getChildCondition()
getAncestorsCondition()
getSiblingsCondition()
Related Links
Inspired by seamless data management.
- MongoDB Model Tree Structures with Materialized Paths
- Inspired by mongoose nested set By @groupdock
- MongooseJS Doc
Changelog
Oct 28, 2017 - version: 0.2.0
- fixed update children behavior. Thanks @selcukfatihsevinc
- updated dependencies: mongoose 4.12.* , Async 2.5.*
- added support nodejs 8.0
- dropped support nodejs 0.6, 0.8
Nov 10, 2016 - version: 0.1.9
- fixed MongoDB 3.2 limit issue. Thanks @alexjamesbrown
- fixed dependency: should package
Aug 15, 2014 - version: 0.1.8
- added new static methods: ToArrayTree(), GetArrayTree(), GetFullArrayTree()
- added new methods: getArrayTree()
- added new tests
- enhancements (toTree, parentId type inherits from _id)
- updated README.md and package dependencies
July 30, 2014 - version: 0.1.7
- fixed remove parent with
parentId=null
bug - added new tests
- updated README.md
Dec 19, 2013 - version: 0.1.6
- added requested function: skip, limit for getDescendants, getChildren, getAncestors, getSiblings
- in tree construction (getTree, buildTree) skip, limit methods is not recommended for use
Oct 15, 2013 - version: 0.1.5
- fixed typo in 153 line.
Jun 25, 2013 - version: 0.1.4
- ToTree use virtuals
- better depth solution
Jun 16, 2013 - version: 0.1.3
- added GetFullTree static method
- added prepare for Building - use: Building({ remove: { lt: 1, gt: 1, level: 1 }, function () { });
- added GetFullTree test
Jun 16, 2013 - version: 0.1.2
- added getTree method and GetTree static method
- added Remove static method for remove with condition
- fixed: getChildren now return promise
- fixed: GetRoots function call
- fixed: GetChildren function call
- Building method already work
- Building tests
- updated README.md
Jun 14, 2013 - version: 0.1.1
- added ToTree test
- tempory removed Building static method (thown not implemented error if use)
- fixed: ToTree now return json document. (Not mongoose document)
- updated README.md
Jun 10, 2013 - version: 0.1.0
- currently under construction
- added test
- static methods
- before save verifies the existence of parent element
- Query supported methods
- added Travis CI build status
- updated README.md
authors
- Janos Meszaros: https://github.com/janez89