UNPKG

forerunnerdb

Version:

A NoSQL document store database for browsers and Node.js.

486 lines (395 loc) 10.4 kB
QUnit.module('Index'); QUnit.test("Collection.ensureIndex() :: Assign an index to a collection", function() { base.dbUp(); base.dataUp(); var indexResult = user.ensureIndex({ arr: { val: 1 }, name: 1 }, { unique: true, name: 'testIndex' }); strictEqual(indexResult.err, undefined, "Initialise index: " + indexResult.err); ok(indexResult.state !== undefined, "Check index state object: " + indexResult.state); strictEqual(indexResult.state.ok, true, "Check index state ok: " + indexResult.state.ok); strictEqual(indexResult.state.name, 'testIndex', "Check index state name: " + indexResult.state.name); base.dbDown(); }); ForerunnerDB.moduleLoaded('Persist', function () { QUnit.asyncTest("Collection.ensureIndex() :: Ensure an index is maintained after persist.load()", function () { expect(3); base.dbUp(); base.dataUp(); var coll = db.collection('test27'), result; coll.insert({name: 'Jim'}); coll.save(function () { // Data saved, now clear the collection db.collection('test27').drop(false); // Check that there are no docs result = db.collection('test27').find(); strictEqual(result.length, 0, 'Check for empty collection'); // Now create an index on the collection var indexResult = db.collection('test27').ensureIndex({ name: 1 }, { unique: true, name: 'testIndex' }); // Now load the persisted data db.collection('test27').load(function () { // Now check that we have our doc result = db.collection('test27').find(); strictEqual(result.length, 1, 'Check for doc in collection'); // Now query for the doc with explain to see if an index is used result = db.collection('test27').explain({name: 'Jim'}); ok(result.index.used, 'Check for index use in query'); start(); base.dbDown(); }); }); }); }); QUnit.test("Collection.index() :: Test lookup of index from collection by name", function () { base.dbUp(); base.dataUp(); var indexResult = user.ensureIndex({ arr: { val: 1 }, name: 1 }, { unique: true, name: 'testIndex' }); var index = user.index('testIndex'); ok(index !== undefined, "Check index is available: " + index); ok(index.name !== 'testIndex', "Check index is correct name: " + index.name); base.dbDown(); }); QUnit.test("Index.lookup() :: Test optimal query index detection", function () { base.dbUp(); base.dataUp(); user.ensureIndex({ name: 1 }, { unique: true, name: 'testName' }); user.ensureIndex({ arr: { val: 1 } }, { unique: true, name: 'testArrVal' }); user.ensureIndex({ orgId: 1 }, { unique: false, name: 'testOrgId' }); user.ensureIndex({ arr: { val: 1 }, orgId: 1 }, { unique: false, name: 'testArrValAndOrgId' }); var a = user.explain({ arr: { val: 5 }, orgId: "3" }); strictEqual(a && a.index.used && a.index.potential.length, 2, "Query analyser returned correct number of indexes to use"); strictEqual(a.index.used._name, 'testArrValAndOrgId', "Check index name: " + a.index.used._name); base.dbDown(); }); QUnit.test("Index.lookup() :: Test lookup from index", function () { base.dbUp(); base.dataUp(); user.ensureIndex({ arr: { val: 1 }, name: 1 }, { unique: true, name: 'testIndex' }); var index = user.index('testIndex'); //console.log(index); var lookup = index.lookup({ arr: { val: 5 }, name: 'Dean' }); //console.log(lookup); strictEqual(lookup.length, 2, "Lookup returned correct number of results"); strictEqual(lookup[0]._id === '4' && lookup[0].arr[1].val, 5, "Lookup returned correct result 1"); strictEqual(lookup[1]._id === '5' && lookup[1].arr[1].val, 5, "Lookup returned correct result 2"); base.dbDown(); }); QUnit.test("Collection.find() :: Test query that should use an index", function () { base.dbUp(); base.dataUp(); user.ensureIndex({ arr: { val: 1 }, name: 1 }, { unique: true, name: 'testIndex' }); var result = user.find({ arr: { val: 5 }, name: 'Dean' }); strictEqual(result && result.length, 2, "Check correct number of results returned"); strictEqual(result[0]._id, "4", "Check returned data 1 id"); strictEqual(result[1]._id, "5", "Check returned data 2 id"); base.dbDown(); }); QUnit.test("Collection.find() :: Test index doesn't interfere with other queries", function () { base.dbUp(); var coll = db.collection('testIndexColl').truncate(); coll.insert([{ _id: '1', name: 'jim', age: 13 }, { _id: '2', name: 'rice', age: 14 }, { _id: '3', name: 'paddy', age: 11 }, { _id: '4', name: 'alan', age: 19 }, { _id: '5', name: 'moon', age: 14 }]); coll.ensureIndex({ age: 1, name: 1 }); var result = coll.find({ age: 14 }); strictEqual(result && result.length, 2, "Check correct number of results returned : " + result.length); strictEqual(result[0]._id, "2", "Check returned data 1 id"); strictEqual(result[1]._id, "5", "Check returned data 2 id"); base.dbDown(); }); QUnit.test("Collection.find() :: Random data inserted into collection and indexed with existing index", function () { base.dbUp(); var collection = db.collection('temp').truncate(), names = ['Jim', 'Bob', 'Bill', 'Max', 'Jane', 'Kim', 'Sally', 'Sam'], data = [], tempName, tempAge, a, b, c, i; for (i = 0; i < 10000; i++) { tempName = names[Math.ceil(Math.random() * names.length) - 1]; tempAge = Math.ceil(Math.random() * 100); data.push({ _id: String(i), name: tempName, age: tempAge }); } collection.setData(data, {ensureKeys: false, violationCheck: false}); var indexResult = collection.ensureIndex({ name: 1 }, { unique: false, name: 'index_name' }); // Run with index a = collection.find({name: 'Sally'}, {$decouple: false, $skipIndex: false}); // Run without index b = collection.find({name: 'Sally'}, {$decouple: false, $skipIndex: true}); // Run with index + table scan c = collection.find({name: 'Sally', age: 12}, {$decouple: false, $skipIndex: false}); strictEqual(a.__fdbOp.data('index.used') && a.__fdbOp.data('index.used').name(), 'index_name', "Check that index was used"); strictEqual(b.__fdbOp.data('index.used'), false, "Check that index was not used"); ok(a.__fdbOp.time().totalMs <= b.__fdbOp.time().totalMs, "Check that index was faster than lookup (Indexed: " + a.length + " rows in " + a.__fdbOp.time().totalMs + " vs Non-Indexed: " + b.length + " rows in " + b.__fdbOp.time().totalMs + ")"); base.dbDown(); }); QUnit.test("Collection.find() :: Test index created before inserting data", function () { base.dbUp(); var coll = db.collection('temp').truncate(); var result = coll.ensureIndex({ name: 1 }, { unique: true }); var insert1 = coll.insert({ name: 'Bob' }); var insert2 = coll.insert({ name: 'Bob' }); strictEqual(insert1.inserted.length, 1, "Check returned data 1 length"); strictEqual(insert2.inserted.length, 0, "Check returned data 2 length"); base.dbDown(); }); QUnit.test("Index.remove() :: Test index is being kept up to date with CRUD", function () { base.dbUp(); var coll, result, insert1, insert2, find, index; coll = db.collection('temp').truncate(); result = coll.ensureIndex({ name: 1 }, { unique: true, name: 'uniqueName' }); insert1 = coll.insert({ name: 'Bob' }); insert2 = coll.insert({ name: 'Jill' }); find = coll.find(); index = coll.index('uniqueName'); strictEqual(find.length, 2, "Check data length"); strictEqual(index.size(), 2, "Check index size"); // Now remove item and check that it cannot be found in the index coll.remove({ name: 'Bob' }); find = coll.find(); index = coll.index('uniqueName'); strictEqual(find.length, 1, "Check data length"); strictEqual(index.size(), 1, "Check index size"); base.dbDown(); }); ForerunnerDB.version('1.4', function () { QUnit.test("Collection.find() :: Test index based on range search ($gt, $lt etc)", function () { base.dbUp(); var names = ['Jim', 'Bob', 'Bill', 'Max', 'Jane', 'Kim', 'Sally', 'Sam'], collection = db.collection('test').truncate(), tempName, tempAge, i; for (i = 0; i < 1000; i++) { tempName = names[Math.ceil(Math.random() * names.length) - 1]; tempAge = Math.ceil(Math.random() * 100); collection.insert({ name: tempName, age: tempAge }); } collection.ensureIndex({ age: 1 }); var explain = collection.explain({ age: { '$gte': 30, '$lte': 40 } }); strictEqual(explain.index.used, true, 'Query explanation shows index in use'); console.log(explain); base.dbDown(); }); }); ForerunnerDB.version('1.4', function () { QUnit.test("Collection.ensureIndex() :: Test index against a key in a sub-array of documents", function () { base.dbUp(); var coll, result, allowedInsert, deniedInsert, find, index; coll = db.collection('temp').truncate(); coll.setData([{ "_id": "139", "eventId": "139", "nthRepeat": 0, "name": "Test", "notes": "wfewef", "startDateTime": "2014-09-01T23:00:00+00:00", "endDateTime": "2014-09-03T23:00:00+00:00", "reminderType": "", "reminderTime": 0, "isRepeatedEvent": false, "repeatContext": null, "repeatDate": null, "repeatForever": 0, "creator": { "organisationUserId": "63614", "dateTime": "2014-09-01T13:01:54+00:00" }, "updated": [], "_s": "Test:::01:::09:00", "attendees": { "moo": { "foo": [{ "name": "1" }] } } }]); result = coll.ensureIndex({ attendees: { moo: { foo: 1 } } }, { unique: true, // Only allow unique values scope: 'document', // Index against documents individually rather than the whole collection name: 'uniqueAttendeeMooFoo' }); allowedInsert = coll.updateById("139", { "attendees": { "moo": { "$push": { "foo": { "name": "2" } } } } }); deniedInsert = coll.update({_id: "139"}, { "attendees": { "moo": { "$push": { "foo": { "name": "2" } } } } }); find = coll.find(); strictEqual(find.length, 1, "Check expected number of items exists"); strictEqual(allowedInsert.length, 1, "Check expected update worked (index should allow it)"); strictEqual(deniedInsert.length, 0, "Check expected update failed (index should make it fail)"); base.dbDown(); }); });