Comparing version 0.6.1 to 0.6.2
@@ -21,6 +21,2 @@ var BinarySearchTree = require('binary-search-tree').BinarySearchTree | ||
* @param {Boolean} options.sparse Optional, allow a sparse index (we can have documents for which fieldName is undefined) (default: false) | ||
* TODO: for now the sparse option doesn't work fully | ||
* don't use it. I will implement it in the future | ||
* in the meantime you can use non-unique, non-sparse indexes | ||
* for approx. the same behaviour | ||
*/ | ||
@@ -46,3 +42,2 @@ function Index (options) { | ||
this.tree = new BinarySearchTree(this.treeOptions); | ||
if (this.sparse) { this.nonindexedDocs = []; } | ||
@@ -66,6 +61,3 @@ if (newData) { this.insert(newData); } | ||
// We don't index documents that don't contain the field if the index is sparse | ||
if (key === undefined && this.sparse) { | ||
this.nonindexedDocs.push(doc); | ||
return; | ||
} | ||
if (key === undefined && this.sparse) { return; } | ||
@@ -116,6 +108,3 @@ this.tree.insert(key, doc); | ||
if (key === undefined && this.sparse) { | ||
this.nonindexedDocs = _.without(this.nonindexedDocs, doc); | ||
return; | ||
} | ||
if (key === undefined && this.sparse) { return; } | ||
@@ -122,0 +111,0 @@ this.tree.delete(key, doc); |
{ | ||
"name": "nedb", | ||
"version": "0.6.1", | ||
"version": "0.6.2", | ||
"author": { | ||
@@ -5,0 +5,0 @@ "name": "tldr.io", |
@@ -7,3 +7,3 @@ # NeDB (Node embedded database) | ||
modules of course). You can **think of it as a SQLite for Node.js projects**, which | ||
can be used with a simple `require` statement. The API is a subset of MongoDB's. | ||
can be used with a simple `require` statement. The API is a subset of MongoDB's. You can use it as a persistent or an in-memory only datastore. | ||
@@ -289,11 +289,15 @@ | ||
Also note that if you use a unique constraint on a field, you will only be able to save one document in which is `undefined`. The second time you do that, the index will reject the document since there is already one with the `undefined` value. I am working on a "sparse" option just like the MongoDB one, enabling indexes to check uniqueness only when the field is defined. | ||
To create an index, use `datastore.ensureIndex(options, cb)`, where callback is optional and get passed an error if any. The options are: | ||
Finally, the `_id` is always indexed with a unique constraint, so queries specifying a value for it are very fast. | ||
* **fieldName** (required): name of the field to index. Use the dot notation to index a field in a nested document. | ||
* **unique** (optional, defaults to `false`): enforce field uniqueness. Note that a unique index will raise an error if you try to index two documents for which the field is not defined. | ||
* **sparse** (optional, defaults to `false`): don't index documents for which the field is not defined. Use this option along with "unique" if you want to accept multiple documents for which it is not defined. | ||
Notes: | ||
* The `_id` is automatically indexed with a unique constraint, so queries specifying a value for it are very fast. | ||
* Currently, indexes are implemented as binary search trees. I will use self-balancing binary search trees in the future to guarantee a consistent performance (the index on `_id` is already balanced since the `_id` is randomly generated). | ||
```javascript | ||
// The syntax is close, but not identical to MongoDB's | ||
// fieldName is of course required | ||
d.ensureIndex({ fieldName: 'somefield' }, function (err) { | ||
db.ensureIndex({ fieldName: 'somefield' }, function (err) { | ||
// If there was an error, err is not null | ||
@@ -303,13 +307,14 @@ }); | ||
// Using a unique constraint with the index | ||
d.ensureIndex({ fieldName: 'somefield', unique: true }, function (err) { | ||
db.ensureIndex({ fieldName: 'somefield', unique: true }, function (err) { | ||
}); | ||
// The ensureIndex method can be called whenever you want: before or after a loadDatabase(), | ||
// after some data was inserted/modified/removed. It will fail to create the index if the | ||
// unique constraint is not satisfied | ||
// Using a sparse unique index | ||
db.ensureIndex({ fieldName: 'somefield', unique: true, sparse: true }, function (err) { | ||
}); | ||
// Format of the error message when the unique constraint is not met | ||
d.insert({ name: 'nedb' }, function (err) { | ||
db.insert({ somefield: 'nedb' }, function (err) { | ||
// err is null | ||
d.insert({ name: 'nedb' }, function (err) { | ||
db.insert({ somefiled: 'nedb' }, function (err) { | ||
// err is { errorType: 'uniqueViolated' | ||
@@ -316,0 +321,0 @@ // , key: 'name' |
@@ -67,5 +67,2 @@ var Index = require('../lib/indexes') | ||
idx.tree.getNumberOfKeys().should.equal(0); // Docs are not indexed | ||
assert.deepEqual(idx.nonindexedDocs, [doc1, doc2]); // Pointers are stored in the non indexed documents | ||
idx.nonindexedDocs[1].a = 12; | ||
doc2.a.should.equal(12); | ||
}); | ||
@@ -157,3 +154,3 @@ | ||
it('If we have a sparse index, we remove the doc from the nonindexedDocs array', function () { | ||
it('If we have a sparse index, removing a non indexed doc has no effect', function () { | ||
var idx = new Index({ fieldName: 'nope', sparse: true }) | ||
@@ -167,7 +164,5 @@ , doc1 = { a: 5, tf: 'hello' } | ||
idx.tree.getNumberOfKeys().should.equal(0); | ||
assert.deepEqual(idx.nonindexedDocs, [doc1, doc2]); | ||
idx.remove(doc1); | ||
idx.tree.getNumberOfKeys().should.equal(0); | ||
assert.deepEqual(idx.nonindexedDocs, [doc2]); | ||
}); | ||
@@ -447,2 +442,58 @@ | ||
it('Can get all documents for a given key in a unique index', function () { | ||
var idx = new Index({ fieldName: 'tf', unique: true }) | ||
, doc1 = { a: 5, tf: 'hello' } | ||
, doc2 = { a: 8, tf: 'world' } | ||
, doc3 = { a: 2, tf: 'bloup' } | ||
; | ||
idx.insert(doc1); | ||
idx.insert(doc2); | ||
idx.insert(doc3); | ||
assert.deepEqual(idx.getMatching('bloup'), [doc3]); | ||
assert.deepEqual(idx.getMatching('world'), [doc2]); | ||
assert.deepEqual(idx.getMatching('nope'), []); | ||
}); | ||
it('Can get all documents for which a field is undefined', function () { | ||
var idx = new Index({ fieldName: 'tf' }) | ||
, doc1 = { a: 5, tf: 'hello' } | ||
, doc2 = { a: 2, nottf: 'bloup' } | ||
, doc3 = { a: 8, tf: 'world' } | ||
, doc4 = { a: 7, nottf: 'yes' } | ||
; | ||
idx.insert(doc1); | ||
idx.insert(doc2); | ||
idx.insert(doc3); | ||
idx.insert(doc4); | ||
assert.deepEqual(idx.getMatching('bloup'), []); | ||
assert.deepEqual(idx.getMatching('hello'), [doc1]); | ||
assert.deepEqual(idx.getMatching('world'), [doc3]); | ||
assert.deepEqual(idx.getMatching('yes'), []); | ||
assert.deepEqual(idx.getMatching(undefined), [doc2, doc4]); | ||
}); | ||
it('Can get all documents for a given key in a sparse index, but not unindexed docs (= field undefined)', function () { | ||
var idx = new Index({ fieldName: 'tf', sparse: true }) | ||
, doc1 = { a: 5, tf: 'hello' } | ||
, doc2 = { a: 2, nottf: 'bloup' } | ||
, doc3 = { a: 8, tf: 'world' } | ||
, doc4 = { a: 7, nottf: 'yes' } | ||
; | ||
idx.insert(doc1); | ||
idx.insert(doc2); | ||
idx.insert(doc3); | ||
idx.insert(doc4); | ||
assert.deepEqual(idx.getMatching('bloup'), []); | ||
assert.deepEqual(idx.getMatching('hello'), [doc1]); | ||
assert.deepEqual(idx.getMatching('world'), [doc3]); | ||
assert.deepEqual(idx.getMatching('yes'), []); | ||
assert.deepEqual(idx.getMatching(undefined), []); | ||
}); | ||
}); // ==== End of 'Get matching documents' ==== // | ||
@@ -527,22 +578,2 @@ | ||
it('Resetting a sparse index resets the nonindexed docs array', function () { | ||
var idx = new Index({ fieldName: 'tf', sparse: true}) | ||
, doc1 = { a: 5, tf: 'hello' } | ||
, doc2 = { a: 8, no: 'world' } | ||
, doc3 = { a: 2, no: 'bloup' } | ||
; | ||
idx.insert(doc1); | ||
idx.insert(doc2); | ||
idx.insert(doc3); | ||
idx.tree.getNumberOfKeys().should.equal(1); | ||
idx.getMatching('hello').length.should.equal(1); | ||
idx.nonindexedDocs.length.should.equal(2); | ||
idx.reset(); | ||
idx.tree.getNumberOfKeys().should.equal(0); | ||
idx.nonindexedDocs.length.should.equal(0); | ||
}); | ||
}); // ==== End of 'Resetting' ==== // | ||
@@ -549,0 +580,0 @@ |
Sorry, the diff of this file is too big to display
196758
4203
379