Skip to content

Commit bc4fe0d

Browse files
committed
mongoose filters for getChildren & getAncestors
1 parent 9019ca3 commit bc4fe0d

File tree

4 files changed

+80
-52
lines changed

4 files changed

+80
-52
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ The path is used for recursive methods and is kept up to date by the plugin if t
7373

7474
Signature:
7575

76-
getChildren([recursive], cb);
76+
getChildren([args], [recursive], cb);
7777

78+
args are additional filters if needed.
7879
if recursive is supplied and true, subchildren are returned
7980

8081
Based on the above hierarchy:
@@ -116,7 +117,7 @@ args is an object you can defined with theses properties :
116117
example: minLevel:2
117118

118119
recursive: boolean, default true
119-
make the search recursive or only fetch childs for the specified level
120+
make the search recursive or only fetch children for the specified level
120121
example: recursive:false
121122

122123
allowEmptyChildren: boolean, default true
@@ -170,7 +171,7 @@ adam.getChildrenTree( function(err, users) {
170171

171172
Signature:
172173

173-
getAncestors(cb);
174+
getAncestors([args], cb);
174175

175176
Based on the above hierarchy:
176177

lib/tree.js

Lines changed: 71 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
var Schema = require('mongoose').Schema;
2-
var _ = require('underscore');
2+
33

44
module.exports = exports = tree;
55

6+
67
/**
78
* @class tree
89
* Tree Behavior for Mongoose
@@ -14,6 +15,7 @@ module.exports = exports = tree;
1415
* @param {Object} options
1516
*/
1617
function tree(schema, options) {
18+
1719
var pathSeparator = options && options.pathSeparator || '#'
1820
, onDelete = options && options.onDelete || 'DELETE'; //'REPARENT'
1921

@@ -37,6 +39,7 @@ function tree(schema, options) {
3739
}
3840
});
3941

42+
4043
/**
4144
* Pre-save middleware
4245
* Build or rebuild path when needed
@@ -54,6 +57,7 @@ function tree(schema, options) {
5457

5558
var self = this;
5659
this.collection.findOne({ _id: this.parent }, function (err, doc) {
60+
5761
if (err) return next(err);
5862

5963
var previousPath = self.path;
@@ -62,33 +66,40 @@ function tree(schema, options) {
6266
if (isParentChange) {
6367
// When the parent is changed we must rewrite all children paths as well
6468
self.collection.find({ path: { '$regex': '^' + previousPath + pathSeparator } }, function (err, cursor) {
69+
6570
if (err) return next(err);
6671

6772
var stream = cursor.stream();
6873
stream.on('data', function (doc) {
6974
var newPath = self.path + doc.path.substr(previousPath.length);
7075
self.collection.update({ _id: doc._id }, { $set: { path: newPath } }, function (err) {
76+
7177
if (err) return next(err);
7278
});
7379
});
80+
7481
stream.on('close', next);
7582
stream.on('error', next);
7683
});
77-
} else {
84+
}
85+
else {
7886
next();
7987
}
8088
});
81-
} else {
89+
}
90+
else {
8291
next();
8392
}
8493
});
8594

95+
8696
/**
8797
* Pre-remove middleware
8898
*
8999
* @param {Function} next
90100
*/
91101
schema.pre('remove', function preRemove(next) {
102+
92103
if (!this.path)
93104
return next();
94105

@@ -102,21 +113,27 @@ function tree(schema, options) {
102113

103114
// Update parent property from children
104115
this.collection.find({ parent: previousParent }, function (err, cursor) {
116+
105117
if (err) return next(err);
106118
var stream = cursor.stream();
107119
stream.on('data', function streamOnData(doc) {
120+
108121
self.collection.update({ _id: doc._id }, { $set: { parent: newParent } }, function (err) {
122+
109123
if (err) return next(err);
110124
});
111125
});
112126
stream.on('close', function streamOnClose() {
127+
113128
// Cascade update Path
114129
self.collection.find({ path: { $regex: previousParent + pathSeparator} }, function (err, cursor) {
115130

116131
var subStream = cursor.stream();
117132
subStream.on('data', function subStreamOnData(doc) {
133+
118134
var newPath = doc.path.replace(previousParent + pathSeparator, '');
119135
self.collection.update({ _id: doc._id }, { $set: { path: newPath } }, function (err) {
136+
120137
if (err) return next(err);
121138
});
122139
});
@@ -130,80 +147,81 @@ function tree(schema, options) {
130147
}
131148
});
132149

150+
133151
/**
134152
* @method getChildren
135153
*
136-
* @param {[type]} recursive
137-
* @param {Function} next
154+
* @param {Object} args
155+
* @param {Boolean} recursive
156+
* @param {Function} next
138157
* @return {Model}
139158
*/
140-
schema.methods.getChildren = function getChildren(recursive, args, next) {
141-
var queryArgs = null;
159+
schema.methods.getChildren = function getChildren(args, recursive, next) {
142160

143-
if (_.isFunction(recursive)) {
144-
next = recursive;
161+
// normalize the arguments
162+
if ("function" === typeof args) {
163+
next = args;
145164
recursive = false;
165+
args = {};
146166
}
147-
148-
if(_.isBoolean(recursive) && _.isFunction(args)){
149-
next = args;
167+
else if ("function" === typeof recursive) {
168+
next = recursive;
169+
if (args instanceof Object) {
170+
recursive = false;
171+
}
172+
else {
173+
recursive = args;
174+
args = {};
175+
}
150176
}
151177

152-
if(_.isObject(recursive)){
153-
queryArgs = recursive;
154-
next = args;
155-
recursive = false;
178+
if (recursive) {
179+
args['path'] = {$regex: '^' + this.path + pathSeparator}
156180
}
157-
158-
if(_.isBoolean(recursive) && _.isObject(args)){
159-
queryArgs = args;
181+
else {
182+
args['parent'] = this._id
160183
}
161184

162-
var filter = recursive ? { path: { $regex: '^' + this.path + pathSeparator } } : { parent: this._id };
163-
if(queryArgs){
164-
filter = _.extend(filter, queryArgs);
165-
}
166-
return this.model(this.constructor.modelName).find(filter, next);
185+
return this.model(this.constructor.modelName).find(args, next);
167186
};
168187

188+
169189
/**
170190
* @method getParent
171191
*
172192
* @param {Function} next
173193
* @return {Model}
174194
*/
175195
schema.methods.getParent = function getParent(next) {
196+
176197
return this.model(this.constructor.modelName).findOne({ _id: this.parent }, next);
177198
};
178199

200+
179201
/**
180202
* @method getAncestors
181203
*
204+
* @param {Object} args
182205
* @param {Function} next
183206
* @return {Model}
184207
*/
185208
schema.methods.getAncestors = function getAncestors(args, next) {
186-
var queryArgs = null;
187209

188-
if(_.isFunction(args)){
210+
if ("function" === typeof args) {
189211
next = args;
212+
args = {};
190213
}
191214

192-
if(_.isObject(args)){
193-
queryArgs = args;
194-
}
215+
var ids = [];
195216

196217
if (this.path) {
197-
var ids = this.path.split(pathSeparator);
218+
ids = this.path.split(pathSeparator);
198219
ids.pop();
199-
} else {
200-
var ids = [];
201220
}
202-
var filter = { _id: { $in: ids } };
203-
if(queryArgs){
204-
filter = _.extend(filter, queryArgs);
205-
}
206-
return this.model(this.constructor.modelName).find(filter, next);
221+
222+
args['_id'] = {$in: ids};
223+
224+
return this.model(this.constructor.modelName).find(args, next);
207225
};
208226

209227

@@ -221,23 +239,23 @@ function tree(schema, options) {
221239
* @param {Function} next
222240
* @return {Model}
223241
*/
224-
schema.statics.getChildrenTree = function getChildrenTree(root, args, cb) {
242+
schema.statics.getChildrenTree = function getChildrenTree(root, args, next) {
225243

226244
if ("function" === typeof(root))
227245
{
228-
cb = root;
246+
next = root;
229247
root = null;
230248
args = {};
231249
}
232250
else if ("function" === typeof(args)) {
233-
cb = args
251+
next = args;
234252

235253
if ("model" in root) {
236254
args = {};
237255
}
238256
else
239257
{
240-
args = root
258+
args = root;
241259
root = null
242260
}
243261
}
@@ -249,7 +267,7 @@ function tree(schema, options) {
249267
var recursive = args.recursive != undefined ? args.recursive : true;
250268
var allowEmptyChildren = args.allowEmptyChildren != undefined ? args.allowEmptyChildren : true;
251269

252-
if (!cb)
270+
if (!next)
253271
throw new Error('no callback defined when calling getChildrenTree');
254272

255273
// filters: Add recursive path filter or not
@@ -284,18 +302,23 @@ function tree(schema, options) {
284302
}
285303

286304
// options:sort , path sort is mandatory
287-
if (!options.sort) options.sort = {};
305+
if (!options.sort) {
306+
options.sort = {};
307+
}
288308
options.sort.path = 1;
289309
options.lean = true;
290310

291311
return this.find(filters, fields, options, function (err, results) {
312+
292313
if (err) throw err;
293314

294315
var getLevel = function (path) {
316+
295317
return path ? path.split(pathSeparator).length : 0;
296318
};
297319

298320
var createChildren = function (arr, node, level) {
321+
299322
if (level == minLevel) {
300323
if (allowEmptyChildren)
301324
node.children = [];
@@ -325,19 +348,23 @@ function tree(schema, options) {
325348
createChildren(finalResults, results[r], level);
326349
}
327350

328-
cb(err, finalResults);
351+
next(err, finalResults);
329352

330353
});
331354
};
332355

356+
333357
schema.methods.getChildrenTree = function(args, cb) {
358+
334359
this.constructor.getChildrenTree(this, args, cb)
335360
};
336361

362+
337363
/**
338364
* @property {Number} level <virtual>
339365
*/
340366
schema.virtual('level').get(function virtualPropLevel() {
367+
341368
return this.path ? this.path.split(pathSeparator).length : 0;
342369
});
343370
}

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"Franck Tab <franck.tab@gmail.com>",
66
"Tomáš Holas <tomas.holas@gmail.com>",
77
"Oleg Butovich <obutovich@gmail.com>",
8+
"Jake Dempsey <angelo0000@gmail.com>",
89
"Alban Escalier (DaWyz)"
910
],
1011
"name": "mongoose-path-tree",
@@ -15,16 +16,15 @@
1516
"url": "git://github.com/swayf/mongoose-path-tree.git"
1617
},
1718
"main": "index.js",
18-
"version": "1.0.2",
19+
"version": "1.1.1",
1920
"engine": "node >= 0.4.0",
2021
"dependencies": {
21-
"mongoose": "3.x.x",
22-
"underscore": "*"
22+
"mongoose": "3.x.x"
2323
},
2424
"devDependencies": {
2525
"async": "0.x.x",
2626
"should": "1.x.x",
27-
"underscore": "1.x.x",
27+
"lodash": "2.x.x",
2828
"mocha": "1.x.x"
2929
},
3030
"directories": {

test/tree.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ var assert = require('assert'),
33
tree = require('../lib/tree'),
44
async = require('async'),
55
should = require('should'),
6-
_ = require('underscore');
6+
_ = require('lodash');
77

88
var Schema = mongoose.Schema;
99

0 commit comments

Comments
 (0)