Socket
Socket
Sign inDemoInstall

nedb

Package Overview
Dependencies
Maintainers
1
Versions
95
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nedb - npm Package Compare versions

Comparing version 0.5.3 to 0.5.4

lib/indexes.js

25

benchmarks/commonUtilities.js

@@ -34,13 +34,18 @@ /**

* Return an array with the numbers from 0 to n-1, in a random order
* Uses Fisher Yates algorithm
* Useful to get fair tests
*/
function getRandomArray (n) {
var res, next;
var res = []
, i, j, temp
;
if (n === 0) { return []; }
if (n === 1) { return [0]; }
for (i = 0; i < n; i += 1) { res[i] = i; }
res = getRandomArray(n - 1);
next = Math.floor(Math.random() * n);
res.splice(next, 0, n - 1); // Add n-1 at a random position in the array
for (i = n - 1; i >= 1; i -= 1) {
j = Math.floor((i + 1) * Math.random());
temp = res[i];
res[i] = res[j];
res[j] = temp;
}

@@ -57,2 +62,3 @@ return res;

var beg = new Date()
, order = getRandomArray(n)
;

@@ -69,3 +75,3 @@

d.insert({ docNumber: i }, function (err) {
d.insert({ docNumber: order[i] }, function (err) {
executeAsap(function () {

@@ -154,3 +160,4 @@ runFrom(i + 1);

d.update({ docNumber: order[i] }, { newDocNumber: i }, options, function (err, nr) {
// Will not actually modify the document but will take the same time
d.update({ docNumber: order[i] }, { docNumber: order[i] }, options, function (err, nr) {
if (nr !== 1) { return cb('One update didnt work'); }

@@ -179,3 +186,3 @@ executeAsap(function () {

if (i === n) { // Finished
console.log("Average time for one remove in a collection of " + n + " docs: " + (profiler.elapsedSinceLastStep() / n) + "ms");
console.log("Average time for one remove and one insert in a collection of " + n + " docs: " + (profiler.elapsedSinceLastStep() / n) + "ms");
profiler.step('Finished removing ' + n + ' docs');

@@ -182,0 +189,0 @@ return cb();

@@ -10,11 +10,26 @@ var Datastore = require('../lib/datastore')

, d = new Datastore(benchDb)
, n = 10000
, program = require('commander')
, n
;
if (process.argv[2]) { n = parseInt(process.argv[2], 10); }
program
.option('-n --number [number]', 'Size of the collection to test on', parseInt)
.option('-i --with-index', 'Test with an index')
.parse(process.argv);
n = program.number || 10000;
console.log("----------------------------");
console.log("Test with " + n + " documents");
console.log(program.withIndex ? "Use an index" : "Don't use an index");
console.log("----------------------------");
async.waterfall([
async.apply(commonUtilities.prepareDb, benchDb)
, function (cb) {
d.loadDatabase(cb);
d.loadDatabase(function (err) {
if (err) { return cb(err); }
if (program.withIndex) { d.ensureIndex({ fieldName: 'docNumber' }); }
cb();
});
}

@@ -21,0 +36,0 @@ , function (cb) { profiler.beginProfiling(); return cb(); }

@@ -10,11 +10,26 @@ var Datastore = require('../lib/datastore')

, d = new Datastore(benchDb)
, n = 10000
, program = require('commander')
, n
;
if (process.argv[2]) { n = parseInt(process.argv[2], 10); }
program
.option('-n --number [number]', 'Size of the collection to test on', parseInt)
.option('-i --with-index', 'Test with an index')
.parse(process.argv);
n = program.number || 10000;
console.log("----------------------------");
console.log("Test with " + n + " documents");
console.log(program.withIndex ? "Use an index" : "Don't use an index");
console.log("----------------------------");
async.waterfall([
async.apply(commonUtilities.prepareDb, benchDb)
, function (cb) {
d.loadDatabase(cb);
d.loadDatabase(function (err) {
if (err) { return cb(err); }
if (program.withIndex) { d.ensureIndex({ fieldName: 'docNumber' }); }
cb();
});
}

@@ -21,0 +36,0 @@ , function (cb) { profiler.beginProfiling(); return cb(); }

@@ -7,12 +7,33 @@ var Datastore = require('../lib/datastore')

, profiler = new execTime('INSERT BENCH')
, n = 10000
, d = new Datastore(benchDb)
, program = require('commander')
, n
;
if (process.argv[2]) { n = parseInt(process.argv[2], 10); }
program
.option('-n --number [number]', 'Size of the collection to test on', parseInt)
.option('-i --with-index', 'Test with an index')
.parse(process.argv);
n = program.number || 10000;
console.log("----------------------------");
console.log("Test with " + n + " documents");
console.log(program.withIndex ? "Use an index" : "Don't use an index");
console.log("----------------------------");
async.waterfall([
async.apply(commonUtilities.prepareDb, benchDb)
, function (cb) {
d.loadDatabase(cb);
d.loadDatabase(function (err) {
if (err) { return cb(err); }
if (program.withIndex) {
d.ensureIndex({ fieldName: 'docNumber' });
n = 2 * n; // We will actually insert twice as many documents
// because the index is slower when the collection is already
// big. So the result given by the algorithm will be a bit worse than
// actual performance
}
cb();
});
}

@@ -19,0 +40,0 @@ , function (cb) { profiler.beginProfiling(); return cb(); }

@@ -10,10 +10,29 @@ var Datastore = require('../lib/datastore')

, d = new Datastore(benchDb)
, n = 10000
, program = require('commander')
, n
;
if (process.argv[2]) { n = parseInt(process.argv[2], 10); }
program
.option('-n --number [number]', 'Size of the collection to test on', parseInt)
.option('-i --with-index', 'Test with an index')
.parse(process.argv);
n = program.number || 10000;
console.log("----------------------------");
console.log("Test with " + n + " documents");
console.log(program.withIndex ? "Use an index" : "Don't use an index");
console.log("----------------------------");
async.waterfall([
async.apply(commonUtilities.prepareDb, benchDb)
, function (cb) { d.loadDatabase(cb); }
, function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err); }
if (program.withIndex) {
d.ensureIndex({ fieldName: 'docNumber' });
}
cb();
});
}
, function (cb) { profiler.beginProfiling(); return cb(); }

@@ -20,0 +39,0 @@ , async.apply(commonUtilities.insertDocs, d, n, profiler)

@@ -10,10 +10,29 @@ var Datastore = require('../lib/datastore')

, d = new Datastore(benchDb)
, n = 10000
, program = require('commander')
, n
;
if (process.argv[2]) { n = parseInt(process.argv[2], 10); }
program
.option('-n --number [number]', 'Size of the collection to test on', parseInt)
.option('-i --with-index', 'Test with an index')
.parse(process.argv);
n = program.number || 10000;
console.log("----------------------------");
console.log("Test with " + n + " documents");
console.log(program.withIndex ? "Use an index" : "Don't use an index");
console.log("----------------------------");
async.waterfall([
async.apply(commonUtilities.prepareDb, benchDb)
, function (cb) { d.loadDatabase(cb); }
, function (cb) {
d.loadDatabase(function (err) {
if (err) { return cb(err); }
if (program.withIndex) {
d.ensureIndex({ fieldName: 'docNumber' });
}
cb();
});
}
, function (cb) { profiler.beginProfiling(); return cb(); }

@@ -20,0 +39,0 @@ , async.apply(commonUtilities.insertDocs, d, n, profiler)

@@ -25,2 +25,4 @@ var fs = require('fs')

* that's not an issue here
* The probability of a collision is extremely small (need 3*10^12 documents to have one chance in a million of a collision)
* See http://en.wikipedia.org/wiki/Birthday_problem
*/

@@ -27,0 +29,0 @@ function uid (len) {

@@ -7,2 +7,5 @@ var fs = require('fs')

, Executor = require('./executor')
, Index = require('./indexes')
, util = require('util')
, _ = require('underscore')
;

@@ -22,2 +25,5 @@

this.datafileSize = 0;
// Indexed by field name, dot notation can be used
this.indexes = {};
}

@@ -27,2 +33,102 @@

/**
* Reset all currently defined indexes
*/
Datastore.prototype.resetIndexes = function (newData) {
var self = this;
Object.keys(this.indexes).forEach(function (i) {
self.indexes[i].reset(newData);
});
};
/**
* Ensure an index is kept for this field. Same parameters as lib/indexes
* For now this function is synchronous, we need to test how much time it takes
* @param {String} options.fieldName
* @param {Boolean} options.unique
* @param {Boolean} options.sparse
* @return {Boolean} true if index was created or already exists, false otherwise
*/
Datastore.prototype.ensureIndex = function (options) {
options = options || {};
if (!options.fieldName) { return false; }
if (this.indexes[options.fieldName]) { return true; }
options.datastore = this;
this.indexes[options.fieldName] = new Index(options);
this.indexes[options.fieldName].insert(this.data);
return true;
};
/**
* Add one or several document(s) to all indexes
*/
Datastore.prototype.addToIndexes = function (doc) {
var self = this;
Object.keys(this.indexes).forEach(function (i) {
self.indexes[i].insert(doc);
});
};
/**
* Remove one or several document(s) from all indexes
*/
Datastore.prototype.removeFromIndexes = function (doc) {
var self = this;
Object.keys(this.indexes).forEach(function (i) {
self.indexes[i].remove(doc);
});
};
/**
* Update a document in all indexes
*/
Datastore.prototype.removeFromIndexes = function (doc, newDoc) {
var self = this;
Object.keys(this.indexes).forEach(function (i) {
self.indexes[i].update(doc, newDoc);
});
};
/**
* Return the list of candidates for a given query
* Very crude implementation for now, we return the candidates given by the first usable index if any
* Also indexes can only be used for direct matches (no $lt, $gt or array yet)
* This still gives a huge performance boost to finds (800x on a collection with 10k documents)
*/
Datastore.prototype.getCandidates = function (query) {
var indexNames = Object.keys(this.indexes)
, usableQueryKeys;
if (indexNames.length === 0) { return this.data; } // No index defined, no specific candidate
// Usable query keys are the ones corresponding to a basic query (no use of $operators or arrays)
usableQueryKeys = [];
Object.keys(query).forEach(function (k) {
if (typeof query[k] === 'string' || typeof query[k] === 'number' || typeof query[k] === 'boolean' || util.isDate(query[k]) || query[k] === null) {
usableQueryKeys.push(k);
}
});
usableQueryKeys = _.intersection(usableQueryKeys, indexNames);
if (usableQueryKeys.length > 0) {
return this.indexes[usableQueryKeys[0]].getMatching(query[usableQueryKeys[0]]);
} else {
return this.data;
}
};
/**
* Load the database

@@ -52,2 +158,3 @@ * This means pulling data out of the data file or creating it if it doesn't exist

self.datafileSize = self.data.length;
self.resetIndexes(self.data);
self.persistCachedDatabase(callback);

@@ -131,6 +238,8 @@ });

, persistableNewDoc
, insertedDoc
;
// Ensure the document has the right format
try {
newDoc._id = newDoc._id || customUtils.uid(16);
newDoc._id = customUtils.uid(16);
persistableNewDoc = model.serialize(newDoc);

@@ -141,7 +250,9 @@ } catch (e) {

insertedDoc = model.deserialize(persistableNewDoc);
fs.appendFile(self.filename, persistableNewDoc + '\n', 'utf8', function (err) {
if (err) { return callback(err); }
var insertedDoc = model.deserialize(persistableNewDoc);
self.data.push(insertedDoc);
self.addToIndexes(insertedDoc);
self.datafileSize += 1;

@@ -164,2 +275,3 @@ return callback(null, model.deepCopy(insertedDoc));

, self = this
, candidates = this.getCandidates(query)
, i

@@ -169,5 +281,5 @@ ;

try {
for (i = 0; i < self.data.length; i += 1) {
if (model.match(self.data[i], query)) {
res.push(model.deepCopy(self.data[i]));
for (i = 0; i < candidates.length; i += 1) {
if (model.match(candidates[i], query)) {
res.push(model.deepCopy(candidates[i]));
}

@@ -189,2 +301,3 @@ }

var self = this
, candidates = this.getCandidates(query)
, i

@@ -194,5 +307,5 @@ ;

try {
for (i = 0; i < self.data.length; i += 1) {
if (model.match(self.data[i], query)) {
return callback(null, model.deepCopy(self.data[i]));
for (i = 0; i < candidates.length; i += 1) {
if (model.match(candidates[i], query)) {
return callback(null, model.deepCopy(candidates[i]));
}

@@ -252,2 +365,3 @@ }

, updatedDocs = []
, candidates
, i

@@ -280,8 +394,10 @@ ;

, function () { // Perform the update
candidates = self.getCandidates(query)
try {
for (i = 0; i < self.data.length; i += 1) {
if (model.match(self.data[i], query) && (multi || numReplaced === 0)) {
for (i = 0; i < candidates.length; i += 1) {
if (model.match(candidates[i], query) && (multi || numReplaced === 0)) {
numReplaced += 1;
self.data[i] = model.modify(self.data[i], updateQuery);
updatedDocs.push(self.data[i]);
candidates[i] = model.modify(candidates[i], updateQuery);
updatedDocs.push(candidates[i]);
}

@@ -318,2 +434,3 @@ }

, self = this
//, candidates = this.getCandidates(query)
, numRemoved = 0

@@ -334,2 +451,3 @@ , multi

removedDocs.push({ $$deleted: true, _id: d._id });
self.removeFromIndexes(d);
} else {

@@ -354,2 +472,4 @@ newData.push(d);

module.exports = Datastore;

@@ -133,2 +133,81 @@ /**

/**
* Utility functions for comparing things
* Assumes type checking was already done (a and b already have the same type)
* compareNSB works for numbers, strings and booleans
*/
function compareNSB (a, b) {
if (a < b) { return -1; }
if (a > b) { return 1; }
return 0;
}
function compareArrays (a, b) {
var i, comp;
for (i = 0; i < Math.min(a.length, b.length); i += 1) {
comp = compareThings(a[i], b[i]);
if (comp !== 0) { return comp; }
}
// Common section was identical, longest one wins
return compareNSB(a.length, b.length);
}
/**
* Compare { things U undefined }
* Things are defined as any native types (string, number, boolean, null, date) and objects
* We need to compare with undefined as it will be used in indexes
* In the case of objects and arrays, we compare the serialized versions
* If two objects dont have the same type, the (arbitrary) type hierarchy is: undefined, null, number, strings, boolean, dates, arrays, objects
* Return -1 if a < b, 1 if a > b and 0 if a = b (note that equality here is NOT the same as defined in areThingsEqual!)
*/
function compareThings (a, b) {
var aKeys, bKeys, comp, i;
// undefined
if (a === undefined) { return b === undefined ? 0 : -1; }
if (b === undefined) { return a === undefined ? 0 : 1; }
// null
if (a === null) { return b === null ? 0 : -1; }
if (b === null) { return a === null ? 0 : 1; }
// Numbers
if (typeof a === 'number') { return typeof b === 'number' ? compareNSB(a, b) : -1; }
if (typeof b === 'number') { return typeof a === 'number' ? compareNSB(a, b) : 1; }
// Strings
if (typeof a === 'string') { return typeof b === 'string' ? compareNSB(a, b) : -1; }
if (typeof b === 'string') { return typeof a === 'string' ? compareNSB(a, b) : 1; }
// Booleans
if (typeof a === 'boolean') { return typeof b === 'boolean' ? compareNSB(a, b) : -1; }
if (typeof b === 'boolean') { return typeof a === 'boolean' ? compareNSB(a, b) : 1; }
// Dates
if (util.isDate(a)) { return util.isDate(b) ? compareNSB(a.getTime(), b.getTime()) : -1; }
if (util.isDate(b)) { return util.isDate(a) ? compareNSB(a.getTime(), b.getTime()) : 1; }
// Arrays (first element is most significant and so on)
if (util.isArray(a)) { return util.isArray(b) ? compareArrays(a, b) : -1; }
if (util.isArray(b)) { return util.isArray(a) ? compareArrays(a, b) : 1; }
// Objects
aKeys = Object.keys(a).sort();
bKeys = Object.keys(b).sort();
for (i = 0; i < Math.min(aKeys.length, bKeys.length); i += 1) {
comp = compareThings(a[aKeys[i]], b[bKeys[i]]);
if (comp !== 0) { return comp; }
}
return compareNSB(aKeys.length, bKeys.length);
}
// ==============================================================

@@ -230,2 +309,3 @@ // Updating documents

checkObject(newDoc);
if (obj._id !== newDoc._id) { throw "You can't change a document's _id"; }
return newDoc;

@@ -483,1 +563,2 @@ };

module.exports.areThingsEqual = areThingsEqual;
module.exports.compareThings = compareThings;
{
"name": "nedb",
"version": "0.5.3",
"version": "0.5.4",
"author": {

@@ -24,3 +24,4 @@ "name": "tldr.io",

"async": "~0.2.8",
"underscore": "~1.4.4"
"underscore": "~1.4.4",
"binary-search-tree": "0.1.2"
},

@@ -32,3 +33,4 @@ "devDependencies": {

"sinon": "1.3.x",
"exec-time": "0.0.2"
"exec-time": "0.0.2",
"commander": "1.1.1"
},

@@ -35,0 +37,0 @@ "scripts": {

@@ -46,4 +46,3 @@ # NeDB (Node embedded database)

If you specify an `_id` field, it will be used as the document's id, otherwise nedb will generate one randomly.
Note that the generated `_id` is a simple string, not an `ObjectId`.
An `_id` field will be automatically generated by NeDB. It's a 16-characters alphanumerical string that cannot be modified once it has been generated. Unlike with MongoDB, you cannot specify it (that shouldn't be a problem anyway).

@@ -193,2 +192,4 @@ Field names cannot begin by '$' or contain a '.'.

**Note**: you can't change a document's _id.
```javascript

@@ -275,8 +276,8 @@ // Let's use the same example collection as in the "finding document" part

As such, it was not designed for speed. That said, it is still pretty fast on the expected datasets (10,000
documents max). On my machine (3 years old, no SSD), with a collection
containing 10,000 documents and with no index (they are not implemented yet):
* An insert takes 0.1 ms
* A read takes 6.4 ms
* An update takes 9.2 ms
* A deletion takes 8.1 ms
documents). On my machine (3 years old, no SSD), with a collection
containing 10,000 documents:
* An insert takes **0.14 ms** (or **0.16 ms** with indexing)
* A read takes **6.4 ms** (or **0.02 ms** with indexing)
* An update takes **9.2 ms** (or **0.2 ms** with indexing)
* A deletion takes 8.1 ms (no speed boost with indexes currently due to the underlying data structure which I will change)

@@ -283,0 +284,0 @@ You can run the simple benchmarks I use by executing the scripts in the `benchmarks` folder. They all take an optional parameter which is the size of the dataset to use (default is 10,000).

@@ -15,5 +15,7 @@ var Datastore = require('../lib/datastore')

describe('Database', function () {
var d = new Datastore(testDb);
var d;
beforeEach(function (done) {
d = new Datastore(testDb);
async.waterfall([

@@ -293,3 +295,3 @@ function (cb) {

it('If an _id is already given when we insert a document, use it and not the default uid', function (done) {
it('If an _id is already given when we insert a document, dont use it but use an automatic one', function (done) {
d.insert({ _id: 'test', stuff: true }, function (err, newDoc) {

@@ -299,3 +301,3 @@ if (err) { return done(err); }

newDoc.stuff.should.equal(true);
newDoc._id.should.equal('test');
newDoc._id.should.not.equal('test');

@@ -823,3 +825,3 @@ done();

d.insert({ a: 2 }, function (err, newDoc) {
d.update({ a: 2 }, { _id: 'nope' }, {}, function (err) {
d.update({ a: 2 }, { a: 2, _id: 'nope' }, {}, function (err) {
assert.isDefined(err);

@@ -833,3 +835,14 @@

done();
d.update({ a: 2 }, { $set: { _id: 'nope' } }, {}, function (err) {
assert.isDefined(err);
d.find({}, function (err, docs) {
docs.length.should.equal(1);
Object.keys(docs[0]).length.should.equal(2);
docs[0].a.should.equal(2);
docs[0]._id.should.equal(newDoc._id);
done();
});
});
});

@@ -1104,2 +1117,160 @@ });

describe('Using indexes', function () {
describe('ensureIndex', function () {
it('ensureIndex can be called right after a loadDatabase and be initialized and filled correctly', function (done) {
var now = new Date()
, rawData = model.serialize({ _id: "aaa", z: "1", a: 2, ages: [1, 5, 12] }) + '\n' +
model.serialize({ _id: "bbb", z: "2", hello: 'world' }) + '\n' +
model.serialize({ _id: "ccc", z: "3", nested: { today: now } })
;
d.data.length.should.equal(0);
d.datafileSize.should.equal(0);
fs.writeFile(testDb, rawData, 'utf8', function () {
d.loadDatabase(function () {
d.data.length.should.equal(3);
d.datafileSize.should.equal(3);
assert.deepEqual(d.indexes, {});
d.ensureIndex({ fieldName: 'z' });
d.indexes.z.fieldName.should.equal('z');
d.indexes.z.unique.should.equal(false);
d.indexes.z.sparse.should.equal(false);
d.indexes.z.tree.getNumberOfKeys().should.equal(3);
d.indexes.z.tree.search('1')[0].should.equal(d.data[0]);
d.indexes.z.tree.search('2')[0].should.equal(d.data[1]);
d.indexes.z.tree.search('3')[0].should.equal(d.data[2]);
done();
});
});
});
it('ensureIndex can be called after the data set was modified and still be correct', function (done) {
var rawData = model.serialize({ _id: "aaa", z: "1", a: 2, ages: [1, 5, 12] }) + '\n' +
model.serialize({ _id: "bbb", z: "2", hello: 'world' })
;
d.data.length.should.equal(0);
d.datafileSize.should.equal(0);
fs.writeFile(testDb, rawData, 'utf8', function () {
d.loadDatabase(function () {
d.data.length.should.equal(2);
d.datafileSize.should.equal(2);
assert.deepEqual(d.indexes, {});
d.insert({ z: "12", yes: 'yes' }, function (err, newDoc1) {
d.insert({ z: "14", nope: 'nope' }, function (err, newDoc2) {
d.remove({ z: "2" }, {}, function () {
d.update({ z: "1" }, { $set: { 'yes': 'yep' } }, {}, function () {
assert.deepEqual(d.indexes, {});
d.ensureIndex({ fieldName: 'z' });
d.indexes.z.fieldName.should.equal('z');
d.indexes.z.unique.should.equal(false);
d.indexes.z.sparse.should.equal(false);
d.indexes.z.tree.getNumberOfKeys().should.equal(3);
d.indexes.z.tree.search('1')[0].should.equal(d.data[0]);
assert.deepEqual(d.data[0], { _id: "aaa", z: "1", a: 2, ages: [1, 5, 12], yes: 'yep' });
d.indexes.z.tree.search('12')[0].should.equal(d.data[1]);
assert.deepEqual(d.data[1], { _id: newDoc1._id, z: "12", yes: 'yes' });
d.indexes.z.tree.search('14')[0].should.equal(d.data[2]);
assert.deepEqual(d.data[2], { _id: newDoc2._id, z: "14", nope: 'nope' });
done();
});
});
});
});
});
});
});
it('ensureIndex can be called before a loadDatabase and still be initialized and filled correctly', function (done) {
var now = new Date()
, rawData = model.serialize({ _id: "aaa", z: "1", a: 2, ages: [1, 5, 12] }) + '\n' +
model.serialize({ _id: "bbb", z: "2", hello: 'world' }) + '\n' +
model.serialize({ _id: "ccc", z: "3", nested: { today: now } })
;
d.data.length.should.equal(0);
d.datafileSize.should.equal(0);
d.ensureIndex({ fieldName: 'z' });
d.indexes.z.fieldName.should.equal('z');
d.indexes.z.unique.should.equal(false);
d.indexes.z.sparse.should.equal(false);
d.indexes.z.tree.getNumberOfKeys().should.equal(0);
fs.writeFile(testDb, rawData, 'utf8', function () {
d.loadDatabase(function () {
d.data.length.should.equal(3);
d.datafileSize.should.equal(3);
d.indexes.z.tree.getNumberOfKeys().should.equal(3);
d.indexes.z.tree.search('1')[0].should.equal(d.data[0]);
d.indexes.z.tree.search('2')[0].should.equal(d.data[1]);
d.indexes.z.tree.search('3')[0].should.equal(d.data[2]);
done();
});
});
});
}); // ==== End of 'ensureIndex' ==== //
describe('Indexing newly inserted documents', function () {
it('Newly inserted documents are indexed', function (done) {
d.ensureIndex({ fieldName: 'z' });
d.indexes.z.tree.getNumberOfKeys().should.equal(0);
d.insert({ a: 2, z: 'yes' }, function (err, newDoc) {
d.indexes.z.tree.getNumberOfKeys().should.equal(1);
assert.deepEqual(d.indexes.z.getMatching('yes'), [newDoc]);
d.insert({ a: 5, z: 'nope' }, function (err, newDoc) {
d.indexes.z.tree.getNumberOfKeys().should.equal(2);
assert.deepEqual(d.indexes.z.getMatching('nope'), [newDoc]);
done();
});
});
});
it('Can insert two docs at the same key for a non unique index', function (done) {
d.ensureIndex({ fieldName: 'z' });
d.indexes.z.tree.getNumberOfKeys().should.equal(0);
d.insert({ a: 2, z: 'yes' }, function (err, newDoc) {
d.indexes.z.tree.getNumberOfKeys().should.equal(1);
assert.deepEqual(d.indexes.z.getMatching('yes'), [newDoc]);
d.insert({ a: 5, z: 'yes' }, function (err, newDoc2) {
d.indexes.z.tree.getNumberOfKeys().should.equal(1);
assert.deepEqual(d.indexes.z.getMatching('yes'), [newDoc, newDoc2]);
done();
});
});
});
}); // ==== End of '' ==== //
}); // ==== End of 'Using indexes' ==== //
});

@@ -332,2 +332,131 @@ var model = require('../lib/model')

describe('Comparing things', function () {
it('undefined is the smallest', function () {
var otherStuff = [null, "string", "", -1, 0, 5.3, 12, true, false, new Date(12345), {}, { hello: 'world' }, [], ['quite', 5]];
model.compareThings(undefined, undefined).should.equal(0);
otherStuff.forEach(function (stuff) {
model.compareThings(undefined, stuff).should.equal(-1);
model.compareThings(stuff, undefined).should.equal(1);
});
});
it('Then null', function () {
var otherStuff = ["string", "", -1, 0, 5.3, 12, true, false, new Date(12345), {}, { hello: 'world' }, [], ['quite', 5]];
model.compareThings(null, null).should.equal(0);
otherStuff.forEach(function (stuff) {
model.compareThings(null, stuff).should.equal(-1);
model.compareThings(stuff, null).should.equal(1);
});
});
it('Then numbers', function () {
var otherStuff = ["string", "", true, false, new Date(4312), {}, { hello: 'world' }, [], ['quite', 5]]
, numbers = [-12, 0, 12, 5.7];
model.compareThings(-12, 0).should.equal(-1);
model.compareThings(0, -3).should.equal(1);
model.compareThings(5.7, 2).should.equal(1);
model.compareThings(5.7, 12.3).should.equal(-1);
model.compareThings(0, 0).should.equal(0);
model.compareThings(-2.6, -2.6).should.equal(0);
model.compareThings(5, 5).should.equal(0);
otherStuff.forEach(function (stuff) {
numbers.forEach(function (number) {
model.compareThings(number, stuff).should.equal(-1);
model.compareThings(stuff, number).should.equal(1);
});
});
});
it('Then strings', function () {
var otherStuff = [true, false, new Date(4321), {}, { hello: 'world' }, [], ['quite', 5]]
, strings = ['', 'string', 'hello world'];
model.compareThings('', 'hey').should.equal(-1);
model.compareThings('hey', '').should.equal(1);
model.compareThings('hey', 'hew').should.equal(1);
model.compareThings('hey', 'hey').should.equal(0);
otherStuff.forEach(function (stuff) {
strings.forEach(function (string) {
model.compareThings(string, stuff).should.equal(-1);
model.compareThings(stuff, string).should.equal(1);
});
});
});
it('Then booleans', function () {
var otherStuff = [new Date(4321), {}, { hello: 'world' }, [], ['quite', 5]]
, bools = [true, false];
model.compareThings(true, true).should.equal(0);
model.compareThings(false, false).should.equal(0);
model.compareThings(true, false).should.equal(1);
model.compareThings(false, true).should.equal(-1);
otherStuff.forEach(function (stuff) {
bools.forEach(function (bool) {
model.compareThings(bool, stuff).should.equal(-1);
model.compareThings(stuff, bool).should.equal(1);
});
});
});
it('Then dates', function () {
var otherStuff = [{}, { hello: 'world' }, [], ['quite', 5]]
, dates = [new Date(-123), new Date(), new Date(5555), new Date(0)]
, now = new Date();
model.compareThings(now, now).should.equal(0);
model.compareThings(new Date(54341), now).should.equal(-1);
model.compareThings(now, new Date(54341)).should.equal(1);
model.compareThings(new Date(0), new Date(-54341)).should.equal(1);
model.compareThings(new Date(123), new Date(4341)).should.equal(-1);
otherStuff.forEach(function (stuff) {
dates.forEach(function (date) {
model.compareThings(date, stuff).should.equal(-1);
model.compareThings(stuff, date).should.equal(1);
});
});
});
it('Then arrays', function () {
var otherStuff = [{}, { hello: 'world' }]
, arrays = [[], ['yes'], ['hello', 5]]
;
model.compareThings([], []).should.equal(0);
model.compareThings(['hello'], []).should.equal(1);
model.compareThings([], ['hello']).should.equal(-1);
model.compareThings(['hello'], ['hello', 'world']).should.equal(-1);
model.compareThings(['hello', 'earth'], ['hello', 'world']).should.equal(-1);
model.compareThings(['hello', 'zzz'], ['hello', 'world']).should.equal(1);
model.compareThings(['hello', 'world'], ['hello', 'world']).should.equal(0);
otherStuff.forEach(function (stuff) {
arrays.forEach(function (array) {
model.compareThings(array, stuff).should.equal(-1);
model.compareThings(stuff, array).should.equal(1);
});
});
});
it('And finally objects', function () {
model.compareThings({}, {}).should.equal(0);
model.compareThings({ a: 42 }, { a: 312}).should.equal(-1);
model.compareThings({ a: '42' }, { a: '312'}).should.equal(1);
model.compareThings({ a: 42, b: 312 }, { b: 312, a: 42 }).should.equal(0);
model.compareThings({ a: 42, b: 312, c: 54 }, { b: 313, a: 42 }).should.equal(-1);
});
}); // ==== End of 'Comparing things' ==== //
describe('Querying', function () {

@@ -334,0 +463,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc