From 5b29286e89140f467ce741216a2c2f7227b6a2ce Mon Sep 17 00:00:00 2001 From: Louis Chatriot Date: Mon, 10 Jun 2013 15:05:32 +0200 Subject: [PATCH] Can use indexes for comparison queries --- lib/datastore.js | 12 ++++++++++++ lib/indexes.js | 11 +++++++++++ test/db.test.js | 23 +++++++++++++++++++++++ test/indexes.test.js | 20 ++++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/lib/datastore.js b/lib/datastore.js index bc9f3e7..283e39b 100644 --- a/lib/datastore.js +++ b/lib/datastore.js @@ -213,6 +213,18 @@ Datastore.prototype.getCandidates = function (query) { return this.indexes[usableQueryKeys[0]].getMatching(query[usableQueryKeys[0]].$in); } + // For a comparison match + usableQueryKeys = []; + Object.keys(query).forEach(function (k) { + if (query[k].hasOwnProperty('$lt') || query[k].hasOwnProperty('$lte') || query[k].hasOwnProperty('$gt') || query[k].hasOwnProperty('$gte')) { + usableQueryKeys.push(k); + } + }); + usableQueryKeys = _.intersection(usableQueryKeys, indexNames); + if (usableQueryKeys.length > 0) { + return this.indexes[usableQueryKeys[0]].getBetweenBounds(query[usableQueryKeys[0]]); + } + // By default, return all the DB data return this.getAllData(); }; diff --git a/lib/indexes.js b/lib/indexes.js index b5bf4e5..a0bb6d7 100644 --- a/lib/indexes.js +++ b/lib/indexes.js @@ -210,6 +210,17 @@ Index.prototype.getMatching = function (value) { }; +/** + * Get all documents in index whose key is between bounds are they are defined by query + * Documents are sorted by key + * @param {Query} query + * @return {Array of documents} + */ +Index.prototype.getBetweenBounds = function (query) { + return this.tree.betweenBounds(query); +}; + + /** * Get all elements in the index * @return {Array of documents} diff --git a/test/db.test.js b/test/db.test.js index a67ccf2..2f499a2 100644 --- a/test/db.test.js +++ b/test/db.test.js @@ -524,6 +524,29 @@ describe('Database', function () { }); }); + it('Can use indexes for comparison matches', function (done) { + d.ensureIndex({ fieldName: 'tf' }, function (err) { + d.insert({ tf: 4 }, function (err, _doc1) { + d.insert({ tf: 6 }, function (err, _doc2) { + d.insert({ tf: 4, an: 'other' }, function (err, _doc3) { + d.insert({ tf: 9 }, function (err, _doc4) { + var data = d.getCandidates({ r: 6, tf: { $lte: 9, $gte: 6 } }) + , doc2 = _.find(data, function (d) { return d._id === _doc2._id; }) + , doc4 = _.find(data, function (d) { return d._id === _doc4._id; }) + ; + + data.length.should.equal(2); + assert.deepEqual(doc2, { _id: doc2._id, tf: 6 }); + assert.deepEqual(doc4, { _id: doc4._id, tf: 9 }); + + done(); + }); + }); + }); + }); + }); + }); + }); // ==== End of '#getCandidates' ==== // diff --git a/test/indexes.test.js b/test/indexes.test.js index 9ccd857..0fc88e9 100644 --- a/test/indexes.test.js +++ b/test/indexes.test.js @@ -548,6 +548,26 @@ describe('Indexes', function () { assert.deepEqual(idx.getMatching(['nope', 'no']), []); }); + it('Can get all documents whose key is between certain bounds', function () { + var idx = new Index({ fieldName: 'a' }) + , doc1 = { a: 5, tf: 'hello' } + , doc2 = { a: 2, tf: 'bloup' } + , doc3 = { a: 8, tf: 'world' } + , doc4 = { a: 7, tf: 'yes' } + , doc5 = { a: 10, tf: 'yes' } + ; + + idx.insert(doc1); + idx.insert(doc2); + idx.insert(doc3); + idx.insert(doc4); + idx.insert(doc5); + + assert.deepEqual(idx.getBetweenBounds({ $lt: 10, $gte: 5 }), [ doc1, doc4, doc3 ]); + assert.deepEqual(idx.getBetweenBounds({ $lte: 8 }), [ doc2, doc1, doc4, doc3 ]); + assert.deepEqual(idx.getBetweenBounds({ $gt: 7 }), [ doc3, doc5 ]); + }); + }); // ==== End of 'Get matching documents' ==== //