1
1
var Schema = require ( 'mongoose' ) . Schema ;
2
2
3
+
3
4
module . exports = exports = tree ;
4
5
6
+
5
7
/**
6
8
* @class tree
7
9
* Tree Behavior for Mongoose
@@ -13,6 +15,7 @@ module.exports = exports = tree;
13
15
* @param {Object } options
14
16
*/
15
17
function tree ( schema , options ) {
18
+
16
19
var pathSeparator = options && options . pathSeparator || '#'
17
20
, onDelete = options && options . onDelete || 'DELETE' ; //'REPARENT'
18
21
@@ -36,6 +39,7 @@ function tree(schema, options) {
36
39
}
37
40
} ) ;
38
41
42
+
39
43
/**
40
44
* Pre-save middleware
41
45
* Build or rebuild path when needed
@@ -53,6 +57,7 @@ function tree(schema, options) {
53
57
54
58
var self = this ;
55
59
this . collection . findOne ( { _id : this . parent } , function ( err , doc ) {
60
+
56
61
if ( err ) return next ( err ) ;
57
62
58
63
var previousPath = self . path ;
@@ -61,33 +66,40 @@ function tree(schema, options) {
61
66
if ( isParentChange ) {
62
67
// When the parent is changed we must rewrite all children paths as well
63
68
self . collection . find ( { path : { '$regex' : '^' + previousPath + pathSeparator } } , function ( err , cursor ) {
69
+
64
70
if ( err ) return next ( err ) ;
65
71
66
72
var stream = cursor . stream ( ) ;
67
73
stream . on ( 'data' , function ( doc ) {
68
74
var newPath = self . path + doc . path . substr ( previousPath . length ) ;
69
75
self . collection . update ( { _id : doc . _id } , { $set : { path : newPath } } , function ( err ) {
76
+
70
77
if ( err ) return next ( err ) ;
71
78
} ) ;
72
79
} ) ;
80
+
73
81
stream . on ( 'close' , next ) ;
74
82
stream . on ( 'error' , next ) ;
75
83
} ) ;
76
- } else {
84
+ }
85
+ else {
77
86
next ( ) ;
78
87
}
79
88
} ) ;
80
- } else {
89
+ }
90
+ else {
81
91
next ( ) ;
82
92
}
83
93
} ) ;
84
94
95
+
85
96
/**
86
97
* Pre-remove middleware
87
98
*
88
99
* @param {Function } next
89
100
*/
90
101
schema . pre ( 'remove' , function preRemove ( next ) {
102
+
91
103
if ( ! this . path )
92
104
return next ( ) ;
93
105
@@ -101,21 +113,27 @@ function tree(schema, options) {
101
113
102
114
// Update parent property from children
103
115
this . collection . find ( { parent : previousParent } , function ( err , cursor ) {
116
+
104
117
if ( err ) return next ( err ) ;
105
118
var stream = cursor . stream ( ) ;
106
119
stream . on ( 'data' , function streamOnData ( doc ) {
120
+
107
121
self . collection . update ( { _id : doc . _id } , { $set : { parent : newParent } } , function ( err ) {
122
+
108
123
if ( err ) return next ( err ) ;
109
124
} ) ;
110
125
} ) ;
111
126
stream . on ( 'close' , function streamOnClose ( ) {
127
+
112
128
// Cascade update Path
113
129
self . collection . find ( { path : { $regex : previousParent + pathSeparator } } , function ( err , cursor ) {
114
130
115
131
var subStream = cursor . stream ( ) ;
116
132
subStream . on ( 'data' , function subStreamOnData ( doc ) {
133
+
117
134
var newPath = doc . path . replace ( previousParent + pathSeparator , '' ) ;
118
135
self . collection . update ( { _id : doc . _id } , { $set : { path : newPath } } , function ( err ) {
136
+
119
137
if ( err ) return next ( err ) ;
120
138
} ) ;
121
139
} ) ;
@@ -129,47 +147,81 @@ function tree(schema, options) {
129
147
}
130
148
} ) ;
131
149
150
+
132
151
/**
133
152
* @method getChildren
134
153
*
135
- * @param {[type] } recursive
136
- * @param {Function } next
154
+ * @param {Object } args
155
+ * @param {Boolean } recursive
156
+ * @param {Function } next
137
157
* @return {Model }
138
158
*/
139
- schema . methods . getChildren = function getChildren ( recursive , next ) {
140
- if ( typeof ( recursive ) === "function" ) {
141
- next = recursive ;
159
+ schema . methods . getChildren = function getChildren ( args , recursive , next ) {
160
+
161
+ // normalize the arguments
162
+ if ( "function" === typeof args ) {
163
+ next = args ;
142
164
recursive = false ;
165
+ args = { } ;
143
166
}
144
- var filter = recursive ? { path : { $regex : '^' + this . path + pathSeparator } } : { parent : this . _id } ;
145
- return this . model ( this . constructor . modelName ) . find ( filter , next ) ;
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
+ }
176
+ }
177
+
178
+ if ( recursive ) {
179
+ args [ 'path' ] = { $regex : '^' + this . path + pathSeparator }
180
+ }
181
+ else {
182
+ args [ 'parent' ] = this . _id
183
+ }
184
+
185
+ return this . model ( this . constructor . modelName ) . find ( args , next ) ;
146
186
} ;
147
187
188
+
148
189
/**
149
190
* @method getParent
150
191
*
151
192
* @param {Function } next
152
193
* @return {Model }
153
194
*/
154
195
schema . methods . getParent = function getParent ( next ) {
196
+
155
197
return this . model ( this . constructor . modelName ) . findOne ( { _id : this . parent } , next ) ;
156
198
} ;
157
199
200
+
158
201
/**
159
202
* @method getAncestors
160
203
*
204
+ * @param {Object } args
161
205
* @param {Function } next
162
206
* @return {Model }
163
207
*/
164
- schema . methods . getAncestors = function getAncestors ( next ) {
208
+ schema . methods . getAncestors = function getAncestors ( args , next ) {
209
+
210
+ if ( "function" === typeof args ) {
211
+ next = args ;
212
+ args = { } ;
213
+ }
214
+
215
+ var ids = [ ] ;
216
+
165
217
if ( this . path ) {
166
- var ids = this . path . split ( pathSeparator ) ;
218
+ ids = this . path . split ( pathSeparator ) ;
167
219
ids . pop ( ) ;
168
- } else {
169
- var ids = [ ] ;
170
220
}
171
- var filter = { _id : { $in : ids } } ;
172
- 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 ) ;
173
225
} ;
174
226
175
227
@@ -187,23 +239,23 @@ function tree(schema, options) {
187
239
* @param {Function } next
188
240
* @return {Model }
189
241
*/
190
- schema . statics . getChildrenTree = function getChildrenTree ( root , args , cb ) {
242
+ schema . statics . getChildrenTree = function getChildrenTree ( root , args , next ) {
191
243
192
244
if ( "function" === typeof ( root ) )
193
245
{
194
- cb = root ;
246
+ next = root ;
195
247
root = null ;
196
248
args = { } ;
197
249
}
198
250
else if ( "function" === typeof ( args ) ) {
199
- cb = args
251
+ next = args ;
200
252
201
253
if ( "model" in root ) {
202
254
args = { } ;
203
255
}
204
256
else
205
257
{
206
- args = root
258
+ args = root ;
207
259
root = null
208
260
}
209
261
}
@@ -215,7 +267,7 @@ function tree(schema, options) {
215
267
var recursive = args . recursive != undefined ? args . recursive : true ;
216
268
var allowEmptyChildren = args . allowEmptyChildren != undefined ? args . allowEmptyChildren : true ;
217
269
218
- if ( ! cb )
270
+ if ( ! next )
219
271
throw new Error ( 'no callback defined when calling getChildrenTree' ) ;
220
272
221
273
// filters: Add recursive path filter or not
@@ -250,18 +302,23 @@ function tree(schema, options) {
250
302
}
251
303
252
304
// options:sort , path sort is mandatory
253
- if ( ! options . sort ) options . sort = { } ;
305
+ if ( ! options . sort ) {
306
+ options . sort = { } ;
307
+ }
254
308
options . sort . path = 1 ;
255
309
options . lean = true ;
256
310
257
311
return this . find ( filters , fields , options , function ( err , results ) {
312
+
258
313
if ( err ) throw err ;
259
314
260
315
var getLevel = function ( path ) {
316
+
261
317
return path ? path . split ( pathSeparator ) . length : 0 ;
262
318
} ;
263
319
264
320
var createChildren = function ( arr , node , level ) {
321
+
265
322
if ( level == minLevel ) {
266
323
if ( allowEmptyChildren )
267
324
node . children = [ ] ;
@@ -291,19 +348,23 @@ function tree(schema, options) {
291
348
createChildren ( finalResults , results [ r ] , level ) ;
292
349
}
293
350
294
- cb ( err , finalResults ) ;
351
+ next ( err , finalResults ) ;
295
352
296
353
} ) ;
297
354
} ;
298
355
356
+
299
357
schema . methods . getChildrenTree = function ( args , cb ) {
358
+
300
359
this . constructor . getChildrenTree ( this , args , cb )
301
360
} ;
302
361
362
+
303
363
/**
304
364
* @property {Number } level <virtual>
305
365
*/
306
366
schema . virtual ( 'level' ) . get ( function virtualPropLevel ( ) {
367
+
307
368
return this . path ? this . path . split ( pathSeparator ) . length : 0 ;
308
369
} ) ;
309
370
}
0 commit comments