From f2025c3995f542b8679e0261346e6271f667a4ef Mon Sep 17 00:00:00 2001 From: Fabien Franzen Date: Thu, 14 Aug 2014 09:40:03 +0200 Subject: [PATCH 1/6] Allow partial list of ids for sortByIds --- lib/dao.js | 32 +++++++++++++++++++++----------- test/basic-querying.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/lib/dao.js b/lib/dao.js index 4ed71b3e..fa00aa4c 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -351,19 +351,29 @@ DataAccessObject.sortByIds = function(ids, results) { return (typeof id === 'object') ? id.toString() : id; }); - results.sort(function(x, y) { - var idA = (typeof x[pk] === 'object') ? x[pk].toString() : x[pk]; - var idB = (typeof y[pk] === 'object') ? y[pk].toString() : y[pk]; - var a = ids.indexOf(idA); - var b = ids.indexOf(idB); - if (a === -1 || b === -1) return 1; // last - if (a !== b) { - if (a > b) return 1; - if (a < b) return -1; - } + var indexOf = function(x) { + var id = (typeof x[pk] === 'object') ? x[pk].toString() : x[pk]; + return ids.indexOf(id); + }; + + var heading = []; + var tailing = []; + + results.forEach(function(x) { + var idx = indexOf(x); + idx === -1 ? tailing.push(x) : heading.push(x); }); - return results; + heading.sort(function(x, y) { + var a = indexOf(x); + var b = indexOf(y); + if (a === -1 || b === -1) return 1; // last + if (a === b) return 0; + if (a > b) return 1; + if (a < b) return -1; + }); + + return heading.concat(tailing); }; function convertNullToNotFoundError(ctx, cb) { diff --git a/test/basic-querying.test.js b/test/basic-querying.test.js index dd26928a..d978fe88 100644 --- a/test/basic-querying.test.js +++ b/test/basic-querying.test.js @@ -87,6 +87,33 @@ describe('basic-querying', function () { done(); }); }); + + it('should sortByIds', function(done) { + User.find(function(err, users) { + sorted = User.sortByIds([6, 5, 4, 3, 2, 1], users); + var names = sorted.map(function(u) { return u.name; }); + names.should.eql(['f', 'e', 'd', 'c', 'b', 'a']); + done(); + }); + }); + + it('should sortByIds - partial ids (1)', function(done) { + User.find(function(err, users) { + sorted = User.sortByIds([6, 5, 4], users); + var names = sorted.map(function(u) { return u.name; }); + names.should.eql(['f', 'e', 'd', 'a', 'b', 'c']); + done(); + }); + }); + + it('should sortByIds - partial ids (2)', function(done) { + User.find(function(err, users) { + sorted = User.sortByIds([5, 3, 2], users); + var names = sorted.map(function(u) { return u.name; }); + names.should.eql(['e', 'c', 'b', 'a', 'd', 'f']); + done(); + }); + }); }); From e6c9de02e2439a1af7c5620928cbb914a6834550 Mon Sep 17 00:00:00 2001 From: Fabien Franzen Date: Thu, 14 Aug 2014 17:13:58 +0200 Subject: [PATCH 2/6] Remove redundant test --- test/basic-querying.test.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/test/basic-querying.test.js b/test/basic-querying.test.js index d978fe88..184335e1 100644 --- a/test/basic-querying.test.js +++ b/test/basic-querying.test.js @@ -97,16 +97,7 @@ describe('basic-querying', function () { }); }); - it('should sortByIds - partial ids (1)', function(done) { - User.find(function(err, users) { - sorted = User.sortByIds([6, 5, 4], users); - var names = sorted.map(function(u) { return u.name; }); - names.should.eql(['f', 'e', 'd', 'a', 'b', 'c']); - done(); - }); - }); - - it('should sortByIds - partial ids (2)', function(done) { + it('should sortByIds - partial ids', function(done) { User.find(function(err, users) { sorted = User.sortByIds([5, 3, 2], users); var names = sorted.map(function(u) { return u.name; }); From 085bb94505e49a85a1203f92771e21f60d098757 Mon Sep 17 00:00:00 2001 From: Fabien Franzen Date: Thu, 14 Aug 2014 09:40:03 +0200 Subject: [PATCH 3/6] Allow partial list of ids for sortByIds --- lib/dao.js | 32 +++++++++++++++++++++----------- test/basic-querying.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/lib/dao.js b/lib/dao.js index 00fbf18c..f2e55a26 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -351,19 +351,29 @@ DataAccessObject.sortByIds = function(ids, results) { return (typeof id === 'object') ? id.toString() : id; }); - results.sort(function(x, y) { - var idA = (typeof x[pk] === 'object') ? x[pk].toString() : x[pk]; - var idB = (typeof y[pk] === 'object') ? y[pk].toString() : y[pk]; - var a = ids.indexOf(idA); - var b = ids.indexOf(idB); - if (a === -1 || b === -1) return 1; // last - if (a !== b) { - if (a > b) return 1; - if (a < b) return -1; - } + var indexOf = function(x) { + var id = (typeof x[pk] === 'object') ? x[pk].toString() : x[pk]; + return ids.indexOf(id); + }; + + var heading = []; + var tailing = []; + + results.forEach(function(x) { + var idx = indexOf(x); + idx === -1 ? tailing.push(x) : heading.push(x); }); - return results; + heading.sort(function(x, y) { + var a = indexOf(x); + var b = indexOf(y); + if (a === -1 || b === -1) return 1; // last + if (a === b) return 0; + if (a > b) return 1; + if (a < b) return -1; + }); + + return heading.concat(tailing); }; function convertNullToNotFoundError(ctx, cb) { diff --git a/test/basic-querying.test.js b/test/basic-querying.test.js index dd26928a..d978fe88 100644 --- a/test/basic-querying.test.js +++ b/test/basic-querying.test.js @@ -87,6 +87,33 @@ describe('basic-querying', function () { done(); }); }); + + it('should sortByIds', function(done) { + User.find(function(err, users) { + sorted = User.sortByIds([6, 5, 4, 3, 2, 1], users); + var names = sorted.map(function(u) { return u.name; }); + names.should.eql(['f', 'e', 'd', 'c', 'b', 'a']); + done(); + }); + }); + + it('should sortByIds - partial ids (1)', function(done) { + User.find(function(err, users) { + sorted = User.sortByIds([6, 5, 4], users); + var names = sorted.map(function(u) { return u.name; }); + names.should.eql(['f', 'e', 'd', 'a', 'b', 'c']); + done(); + }); + }); + + it('should sortByIds - partial ids (2)', function(done) { + User.find(function(err, users) { + sorted = User.sortByIds([5, 3, 2], users); + var names = sorted.map(function(u) { return u.name; }); + names.should.eql(['e', 'c', 'b', 'a', 'd', 'f']); + done(); + }); + }); }); From c599de42cdd7f3c68158a742d313f73727e238e7 Mon Sep 17 00:00:00 2001 From: Fabien Franzen Date: Thu, 14 Aug 2014 17:13:58 +0200 Subject: [PATCH 4/6] Remove redundant test --- test/basic-querying.test.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/test/basic-querying.test.js b/test/basic-querying.test.js index d978fe88..184335e1 100644 --- a/test/basic-querying.test.js +++ b/test/basic-querying.test.js @@ -97,16 +97,7 @@ describe('basic-querying', function () { }); }); - it('should sortByIds - partial ids (1)', function(done) { - User.find(function(err, users) { - sorted = User.sortByIds([6, 5, 4], users); - var names = sorted.map(function(u) { return u.name; }); - names.should.eql(['f', 'e', 'd', 'a', 'b', 'c']); - done(); - }); - }); - - it('should sortByIds - partial ids (2)', function(done) { + it('should sortByIds - partial ids', function(done) { User.find(function(err, users) { sorted = User.sortByIds([5, 3, 2], users); var names = sorted.map(function(u) { return u.name; }); From 9f1c5d9c378ce01bf73fa358e292e6902ec839e9 Mon Sep 17 00:00:00 2001 From: Fabien Franzen Date: Fri, 15 Aug 2014 19:39:18 +0200 Subject: [PATCH 5/6] Moved DataAccessObject.sortByIds to utils.js --- lib/dao.js | 33 +------------------------------- lib/utils.js | 38 ++++++++++++++++++++++++++++++++++++- test/basic-querying.test.js | 18 ------------------ test/util.test.js | 26 +++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 51 deletions(-) diff --git a/lib/dao.js b/lib/dao.js index f2e55a26..6595a576 100644 --- a/lib/dao.js +++ b/lib/dao.js @@ -341,41 +341,10 @@ DataAccessObject.findByIds = function(ids, cond, cb) { filter.where[pk] = { inq: ids }; mergeQuery(filter, cond || {}); this.find(filter, function(err, results) { - cb(err, err ? results : this.sortByIds(ids, results)); + cb(err, err ? results : utils.sortObjectsByIds(pk, ids, results)); }.bind(this)); }; -DataAccessObject.sortByIds = function(ids, results) { - var pk = this.dataSource.idName(this.modelName) || 'id'; - ids = ids.map(function(id) { - return (typeof id === 'object') ? id.toString() : id; - }); - - var indexOf = function(x) { - var id = (typeof x[pk] === 'object') ? x[pk].toString() : x[pk]; - return ids.indexOf(id); - }; - - var heading = []; - var tailing = []; - - results.forEach(function(x) { - var idx = indexOf(x); - idx === -1 ? tailing.push(x) : heading.push(x); - }); - - heading.sort(function(x, y) { - var a = indexOf(x); - var b = indexOf(y); - if (a === -1 || b === -1) return 1; // last - if (a === b) return 0; - if (a > b) return 1; - if (a < b) return -1; - }); - - return heading.concat(tailing); -}; - function convertNullToNotFoundError(ctx, cb) { if (ctx.result !== null) return cb(); diff --git a/lib/utils.js b/lib/utils.js index 520cf462..087cd615 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -6,6 +6,7 @@ exports.parseSettings = parseSettings; exports.mergeSettings = mergeSettings; exports.isPlainObject = isPlainObject; exports.defineCachedRelations = defineCachedRelations; +exports.sortObjectsByIds = sortObjectsByIds; var traverse = require('traverse'); @@ -203,4 +204,39 @@ function defineCachedRelations(obj) { function isPlainObject(obj) { return (typeof obj === 'object') && (obj !== null) && (obj.constructor === Object); -} \ No newline at end of file +} + + + +function sortObjectsByIds(idName, ids, objects) { + ids = ids.map(function(id) { + return (typeof id === 'object') ? id.toString() : id; + }); + + var indexOf = function(x) { + var isObj = (typeof x[idName] === 'object'); // ObjectID + var id = isObj ? x[idName].toString() : x[idName]; + return ids.indexOf(id); + }; + + var heading = []; + var tailing = []; + + objects.forEach(function(x) { + if (typeof x === 'object') { + var idx = indexOf(x); + idx === -1 ? tailing.push(x) : heading.push(x); + } + }); + + heading.sort(function(x, y) { + var a = indexOf(x); + var b = indexOf(y); + if (a === -1 || b === -1) return 1; // last + if (a === b) return 0; + if (a > b) return 1; + if (a < b) return -1; + }); + + return heading.concat(tailing); +}; diff --git a/test/basic-querying.test.js b/test/basic-querying.test.js index 184335e1..dd26928a 100644 --- a/test/basic-querying.test.js +++ b/test/basic-querying.test.js @@ -87,24 +87,6 @@ describe('basic-querying', function () { done(); }); }); - - it('should sortByIds', function(done) { - User.find(function(err, users) { - sorted = User.sortByIds([6, 5, 4, 3, 2, 1], users); - var names = sorted.map(function(u) { return u.name; }); - names.should.eql(['f', 'e', 'd', 'c', 'b', 'a']); - done(); - }); - }); - - it('should sortByIds - partial ids', function(done) { - User.find(function(err, users) { - sorted = User.sortByIds([5, 3, 2], users); - var names = sorted.map(function(u) { return u.name; }); - names.should.eql(['e', 'c', 'b', 'a', 'd', 'f']); - done(); - }); - }); }); diff --git a/test/util.test.js b/test/util.test.js index 81de4a75..37da6fe5 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -3,6 +3,7 @@ var utils = require('../lib/utils'); var fieldsToArray = utils.fieldsToArray; var removeUndefined = utils.removeUndefined; var mergeSettings = utils.mergeSettings; +var sortObjectsByIds = utils.sortObjectsByIds; describe('util.fieldsToArray', function () { it('Turn objects and strings into an array of fields to include when finding models', function () { @@ -185,4 +186,29 @@ describe('mergeSettings', function () { should.deepEqual(dst.acls, expected.acls, 'Merged settings should match the expectation'); }); +}); + +describe('sortObjectsByIds', function () { + + var items = [ + { id: 1, name: 'a' }, + { id: 2, name: 'b' }, + { id: 3, name: 'c' }, + { id: 4, name: 'd' }, + { id: 5, name: 'e' }, + { id: 6, name: 'f' } + ]; + + it('should sort', function() { + var sorted = sortObjectsByIds('id', [6, 5, 4, 3, 2, 1], items); + var names = sorted.map(function(u) { return u.name; }); + should.deepEqual(names, ['f', 'e', 'd', 'c', 'b', 'a']); + }); + + it('should sort - partial ids', function() { + var sorted =sortObjectsByIds('id', [5, 3, 2], items); + var names = sorted.map(function(u) { return u.name; }); + should.deepEqual(names, ['e', 'c', 'b', 'a', 'd', 'f']); + }); + }); \ No newline at end of file From 3e300c1f35000e3258666cc4dc25960e365a0755 Mon Sep 17 00:00:00 2001 From: Fabien Franzen Date: Fri, 15 Aug 2014 19:47:12 +0200 Subject: [PATCH 6/6] Add strict flag to sortObjectsByIds When true, any object not in the ids will be discarded and a subset will be returned. --- lib/utils.js | 3 ++- test/util.test.js | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 087cd615..6afb9129 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -208,7 +208,7 @@ function isPlainObject(obj) { -function sortObjectsByIds(idName, ids, objects) { +function sortObjectsByIds(idName, ids, objects, strict) { ids = ids.map(function(id) { return (typeof id === 'object') ? id.toString() : id; }); @@ -225,6 +225,7 @@ function sortObjectsByIds(idName, ids, objects) { objects.forEach(function(x) { if (typeof x === 'object') { var idx = indexOf(x); + if (strict && idx === -1) return; idx === -1 ? tailing.push(x) : heading.push(x); } }); diff --git a/test/util.test.js b/test/util.test.js index 37da6fe5..f933190a 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -206,9 +206,15 @@ describe('sortObjectsByIds', function () { }); it('should sort - partial ids', function() { - var sorted =sortObjectsByIds('id', [5, 3, 2], items); + var sorted = sortObjectsByIds('id', [5, 3, 2], items); var names = sorted.map(function(u) { return u.name; }); should.deepEqual(names, ['e', 'c', 'b', 'a', 'd', 'f']); }); + + it('should sort - strict', function() { + var sorted = sortObjectsByIds('id', [5, 3, 2], items, true); + var names = sorted.map(function(u) { return u.name; }); + should.deepEqual(names, ['e', 'c', 'b']); + }); -}); \ No newline at end of file +});