Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Performance improvements in wrapping objects

  • Loading branch information...
commit a8971584239461271db4c5fb649dbdb5f1476f84 1 parent b4ec2ce
Joshua Gross authored

Showing 3 changed files with 56 additions and 27 deletions. Show diff stats Hide diff stats

  1. +36 16 lib/mongoose-subpopulate.js
  2. +1 1  package.json
  3. +19 10 test/mongoose.js
52 lib/mongoose-subpopulate.js
@@ -26,11 +26,15 @@ var wrapSchema = exports.wrapSchema = function wrapSchema (schema) {
26 26 }
27 27 return function (err, result) {
28 28 if (callback.length === 2) {
29   - return callback(err, wrapModelObject(result));
  29 + wrapModelObject(result, function (wrapped) {
  30 + return callback(err, wrapped);
  31 + });
30 32 } else if (err) {
31 33 throw new Error('Database error: '+errMsg+' / '+err);
32 34 } else {
33   - return callback(wrapModelObject(result));
  35 + wrapModelObject(result, function (wrapped) {
  36 + return callback(wrapped);
  37 + });
34 38 }
35 39 };
36 40 };
@@ -286,19 +290,35 @@ function getCallerDetails () {
286 290 // 1) Directly access the _id attribute as a string
287 291 // 2) Get and set attributes of the object; all changes are synced immediately with the mongoose link
288 292 // 3) Get a bare dictionary of the model and any populated descendants
289   -function wrapModelObject (object) {
  293 +function wrapModelObject (object, callback) {
290 294 if (object === null || object === undefined) {
291   - return object;
  295 + return (callback ? callback(object) : object);
292 296 }
293 297
294 298 // Is this an array?
295 299 if (!object._schema /* 2.7 */ && !object.schema /* 3.x */) {
296   - for (var i in object) {
297   - if (object[i] && (object[i]._schema || object[i].schema)) {
298   - object[i] = wrapModelObject(object[i]);
  300 + if (callback) {
  301 + return async.map(object, function (obj, iterate) {
  302 + if (obj && (obj._schema || obj.schema)) {
  303 + process.nextTick(function () {
  304 + wrapModelObject(obj, function (wrappedObject) {
  305 + iterate(null, wrappedObject);
  306 + });
  307 + });
  308 + } else {
  309 + iterate(null, obj);
  310 + }
  311 + }, function (err, wrappedObject) {
  312 + return callback(wrappedObject);
  313 + });
  314 + } else {
  315 + for (var i in object) {
  316 + if (object[i] && (object[i]._schema || object[i].schema)) {
  317 + object[i] = wrapModelObject(object[i]);
  318 + }
299 319 }
  320 + return object;
300 321 }
301   - return object;
302 322 }
303 323
304 324 var wrappedObject = new (function wrapped () {})();
@@ -307,16 +327,16 @@ function wrapModelObject (object) {
307 327
308 328 for (var i in object) {
309 329 if (typeof object[i] === 'function') {
310   - if ((!i.match(/^to/) || i.match(/^toObject/)) && 'inspect' != i) {
  330 + if ((i.substr(0,2) !== 'to' || i === 'toObject') && 'inspect' !== i) {
311 331 (function (attr) {
312   - wrappedObject[attr] = function () {
  332 + wrappedObject.__proto__[attr] = function () {
313 333 return object[attr].apply(object, arguments);
314 334 }
315 335 })(i);
316 336 }
317 337 } else {
318 338 (function (attr) {
319   - wrappedObject.__defineGetter__(attr, function () {
  339 + wrappedObject.__proto__.__defineGetter__(attr, function () {
320 340 return object[attr];
321 341 });
322 342 })(i);
@@ -327,7 +347,7 @@ function wrapModelObject (object) {
327 347 var schema = (object._schema || object.schema).paths;
328 348 for (var i in schema) {
329 349 (function (attr) {
330   - wrappedObject.__defineGetter__(attr, function () {
  350 + wrappedObject.__proto__.__defineGetter__(attr, function () {
331 351 // Sometimes the object will have an undefined value, but something is hanging out in object._docs
332 352 ('undefined' === typeof object[attr] && 'undefined' !== typeof object._doc && 'undefined' !== typeof object._doc[attr]) && (object[attr] = object._doc[attr]);
333 353
@@ -357,7 +377,7 @@ function wrapModelObject (object) {
357 377 return object[attr];
358 378 }
359 379 });
360   - wrappedObject.__defineSetter__(attr, function (value) {
  380 + wrappedObject.__proto__.__defineSetter__(attr, function (value) {
361 381 // Cache object references; Mongoose casts them to IDs and they're sort of lost.
362 382 if (value && value.mongooseLink) {
363 383 wrappedObject.populatedObjects[value._id] = value;
@@ -376,11 +396,11 @@ function wrapModelObject (object) {
376 396 // Allow all methods (from plugins, etc) to be accessed
377 397 for (var i in wrappedObject.schema.methods) {
378 398 (function (methodName) {
379   - wrappedObject[methodName] = wrappedObject.schema.methods[methodName];
  399 + wrappedObject.__proto__[methodName] = wrappedObject.schema.methods[methodName];
380 400 })(i);
381 401 }
382 402
383   - wrappedObject.getBare = function (callback) {
  403 + wrappedObject.__proto__.getBare = function (callback) {
384 404 var keys = Object.keys(wrappedObject.schema.paths);
385 405
386 406 var bareDictionary = {};
@@ -399,7 +419,7 @@ function wrapModelObject (object) {
399 419 });
400 420 };
401 421
402   - return wrappedObject;
  422 + return (callback ? callback(wrappedObject) : wrappedObject);
403 423 }
404 424 exports.extendMongoose = function (mongooseIn, defineModels) {
405 425 mongoose = mongooseIn;
2  package.json
... ... @@ -1,6 +1,6 @@
1 1 {
2 2 "name": "mongoose-subpopulate",
3   - "version": "0.1.10",
  3 + "version": "0.1.11",
4 4 "main": "./lib/mongoose-subpopulate.js",
5 5 "scripts": {},
6 6 "repository": {
29 test/mongoose.js
@@ -146,12 +146,12 @@ describe('mongoose wrapping of find, exec, etc', function () {
146 146 }
147 147 });
148 148 // TODO: rigorously test this
149   - /*it('should handle errors from object creation', function (done) {
150   - var m = common.db();
  149 + //it('should handle errors from object creation', function (done) {
  150 + //var m = common.db();
151 151 // leave necessary fields empty
152   - var u = new m.User();
153   - u.save(done);
154   - });*/
  152 + //var u = new m.User();
  153 + //u.save(done);
  154 + //});
155 155 it('should wrap errors from findOne', function (done) {
156 156 var m = common.db();
157 157 m.User.findOne({ _id: findOneID }, function (user) {
@@ -370,9 +370,9 @@ describe('mongoose additions bugs', function () {
370 370 });
371 371 });
372 372 });
373   -/*describe('mongoose large record handling', function () {
  373 +describe('mongoose large record handling', function () {
374 374 it('should be able to create large amounts of records', function (done) {
375   - this.timeout(10000);
  375 + this.timeout(0);
376 376 var m = common.db();
377 377 var ids = [];
378 378 for (var i = 0; i < 1000; i++) {
@@ -391,11 +391,20 @@ describe('mongoose additions bugs', function () {
391 391 });
392 392 });
393 393 it('should be able to fetch large amounts of records', function (done) {
394   - this.timeout(10000);
  394 + this.timeout(0);
395 395 var m = common.db();
396 396 m.User.find().exec(function (users) {
397 397 expect(users.length).to.be.greaterThan(1000);
398   - done();
  398 + async.map(users, function (u, iterate) {
  399 + var newEmail = u.email+'.uk';
  400 + u.email = newEmail;
  401 + u.save(function (err, newU) {
  402 + expect(newU.email).to.be(newEmail);
  403 + iterate(null, null);
  404 + });
  405 + }, function () {
  406 + done();
  407 + });
399 408 });
400 409 });
401   -});*/
  410 +});

0 comments on commit a897158

Please sign in to comment.
Something went wrong with that request. Please try again.