Fix multiple sort criteria

With larger datasets, the sorting was incorrect. Now, instead of
sorting the array multiple times, multiple criteria are considered
in a single pass.
pull/2/head
Tim Shadel 11 years ago
parent 7e04658d69
commit 9a917a6d57
  1. 17
      lib/cursor.js
  2. 43
      test/cursor.test.js

@ -85,12 +85,21 @@ Cursor.prototype._exec = function(callback) {
keys = Object.keys(this._sort); keys = Object.keys(this._sort);
// Going backwards so that the first sort is the last that gets applied // Going backwards so that the first sort is the last that gets applied
for (i = keys.length - 1; i >= 0; i -= 1) { var criteria = [];
for (i = 0; i < keys.length; i++) {
key = keys[i]; key = keys[i];
res.sort(function(a, b) { criteria.push({ key: key, direction: self._sort[key] });
return self._sort[key] * model.compareThings(model.getDotValue(a, key), model.getDotValue(b, key));
});
} }
res.sort(function(a, b) {
for (var i = 0; i < criteria.length; i++) {
var criterion = criteria[i];
var compare = criterion.direction * model.compareThings(model.getDotValue(a, criterion.key), model.getDotValue(b, criterion.key));
if (compare !== 0) {
return compare;
}
}
return 0;
});
// Applying limit and skip // Applying limit and skip
var limit = this._limit || res.length var limit = this._limit || res.length

@ -605,6 +605,49 @@ describe('Cursor', function () {
} }
], done); }); ], done); });
it('Similar data, multiple consecutive sorts', function(done) {
async.waterfall([
function (cb) {
d.remove({}, { multi: true }, function (err) {
if (err) { return cb(err); }
var entities = [];
var companies = [ 'acme', 'milkman', 'zoinks' ];
var id = 1;
for (var i = 0; i < companies.length; i++) {
for (var j = 5; j <= 100; j += 5) {
entities.push({
company: companies[i],
cost: j,
nid: id
});
id++;
}
}
async.each(entities, function(entity, callback) {
d.insert(entity, function() {
callback();
});
}, function(err) {
return cb();
});
});
}
, function (cb) {
var cursor = new Cursor(d, {});
cursor.sort({ company: 1, cost: 1 }).exec(function (err, docs) {
docs.length.should.equal(60);
for (var i = 0; i < docs.length; i++) {
docs[i].nid.should.equal(i+1);
};
return cb();
});
}
], done); });
}); // ===== End of 'Sorting' ===== }); // ===== End of 'Sorting' =====
}); });

Loading…
Cancel
Save