Comparing version 1.2.3 to 1.2.4
@@ -1,3 +0,3 @@ | ||
var loki = require('../src/lokijs.js'), | ||
db = new loki('perftest'), | ||
// var loki = require('../src/lokijs.js'), | ||
var db = new loki('perftest'), | ||
samplecoll = null, | ||
@@ -8,3 +8,3 @@ arraySize = 5000, // how large of a dataset to generate | ||
getIterations = 2000000; // get is crazy fast due to binary search so this needs separate scale | ||
function genRandomVal() | ||
@@ -23,3 +23,3 @@ { | ||
// (customId) which is number from 1- totalIterations | ||
// we will later perform find() queries against customId with and | ||
// we will later perform find() queries against customId with and | ||
// without an index | ||
@@ -29,3 +29,3 @@ | ||
db = new loki('perftest'); | ||
var start, end, totalTime; | ||
@@ -35,3 +35,3 @@ var totalTimes = []; | ||
samplecoll = db.addCollection('samplecoll'); | ||
samplecoll = db.addCollection('samplecoll'); | ||
/* | ||
@@ -42,27 +42,28 @@ { | ||
transactional: false, | ||
clone: false | ||
clone: false | ||
} | ||
); | ||
); | ||
*/ | ||
for (var idx=0; idx < arraySize; idx++) { | ||
var v1 = genRandomVal(); | ||
var v2 = genRandomVal(); | ||
start = process.hrtime(); | ||
samplecoll.insert({ | ||
customId: idx, | ||
val: v1, | ||
val2: v2, | ||
// start = process.hrtime(); | ||
start = performance.now(); | ||
samplecoll.insert({ | ||
customId: idx, | ||
val: v1, | ||
val2: v2, | ||
val3: "more data 1234567890" | ||
}); | ||
end = process.hrtime(start); | ||
totalTimes.push(end); | ||
end = performance.now() - start; | ||
totalTimes.push([0, end * 1e6]); | ||
} | ||
for(var idx=0; idx < totalTimes.length; idx++) { | ||
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1]/1e6; | ||
} | ||
//var totalMS = end[0] * 1e3 + end[1]/1e6; | ||
@@ -82,3 +83,3 @@ totalMS = totalMS.toFixed(2); | ||
var dbTest = new loki('perfInsertWithEval'); | ||
var start, end, totalTime; | ||
@@ -88,3 +89,3 @@ var totalTimes = []; | ||
var coll = dbTest.addCollection('samplecoll', | ||
var coll = dbTest.addCollection('samplecoll', | ||
{ | ||
@@ -98,21 +99,23 @@ indices: ['customId'], | ||
); | ||
var dv = coll.addDynamicView('test'); | ||
dv.applyFind({'customId': {'$lt': arraySize/4 }}); | ||
for (var idx=0; idx < arraySize; idx++) { | ||
var v1 = genRandomVal(); | ||
var v2 = genRandomVal(); | ||
start = process.hrtime(); | ||
coll.insert({ | ||
customId: idx, | ||
val: v1, | ||
val2: v2, | ||
// start = process.hrtime(); | ||
start = performance.now(); | ||
coll.insert({ | ||
customId: idx, | ||
val: v1, | ||
val2: v2, | ||
val3: "more data 1234567890" | ||
}); | ||
end = process.hrtime(start); | ||
totalTimes.push(end); | ||
// end = process.hrtime(start); | ||
end = performance.now() - start; | ||
totalTimes.push([0, end * 1e6]); | ||
} | ||
for(var idx=0; idx < totalTimes.length; idx++) { | ||
@@ -132,16 +135,18 @@ totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1]/1e6; | ||
var totalMS = 0.0; | ||
for (var idx=0; idx < getIterations; idx++) { | ||
var customidx = Math.floor(Math.random() * arraySize) + 1; | ||
start = process.hrtime(); | ||
// start = process.hrtime(); | ||
start = performance.now(); | ||
var results = samplecoll.get(customidx); | ||
end = process.hrtime(start); | ||
totalTimes.push(end); | ||
// end = process.hrtime(start); | ||
end = performance.now() - start; | ||
totalTimes.push([0, end * 1e6]); | ||
} | ||
for(var idx=0; idx < totalTimes.length; idx++) { | ||
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1]/1e6; | ||
} | ||
totalMS = totalMS.toFixed(2); | ||
@@ -162,16 +167,18 @@ var rate = getIterations * 1000 / totalMS; | ||
} | ||
for (var idx=0; idx < loopIterations; idx++) { | ||
var customidx = Math.floor(Math.random() * arraySize) + 1; | ||
start = process.hrtime(); | ||
// start = process.hrtime(); | ||
start = performance.now(); | ||
var results = samplecoll.find({ 'customId': customidx }); | ||
end = process.hrtime(start); | ||
totalTimes.push(end); | ||
// end = process.hrtime(start); | ||
end = performance.now() - start; | ||
totalTimes.push([0, end * 1e6]); | ||
} | ||
for(var idx=0; idx < totalTimes.length; idx++) { | ||
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1]/1e6; | ||
} | ||
totalMS = totalMS.toFixed(2); | ||
@@ -192,16 +199,18 @@ var rate = loopIterations * 1000 / totalMS; | ||
} | ||
for (var idx=0; idx < loopIterations; idx++) { | ||
var customidx = Math.floor(Math.random() * arraySize) + 1; | ||
start = process.hrtime(); | ||
// start = process.hrtime(); | ||
start = performance.now(); | ||
var results = samplecoll.chain().find({ 'customId': customidx }).data(); | ||
end = process.hrtime(start) | ||
totalTimes.push(end); | ||
// end = process.hrtime(start) | ||
end = performance.now() - start; | ||
totalTimes.push([0, end * 1e6]); | ||
} | ||
for(var idx=0; idx < totalTimes.length; idx++) { | ||
totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1]/1e6; | ||
} | ||
totalMS = totalMS.toFixed(2); | ||
@@ -220,3 +229,3 @@ var rate = loopIterations * 1000 / totalMS; | ||
var totalMS2 = 0; | ||
var loopIterations = totalIterations; | ||
@@ -226,22 +235,26 @@ if (typeof(multiplier) != "undefined") { | ||
} | ||
for (var idx=0; idx < loopIterations; idx++) { | ||
var customidx = Math.floor(Math.random() * arraySize) + 1; | ||
start = process.hrtime(); | ||
// start = process.hrtime(); | ||
start = performance.now(); | ||
var dv = samplecoll.addDynamicView("perfview"); | ||
dv.applyFind({ 'customId': customidx }); | ||
var results = dv.data(); | ||
end = process.hrtime(start); | ||
totalTimes.push(end); | ||
// end = process.hrtime(start); | ||
end = performance.now() - start; | ||
totalTimes.push([0, end * 1e6]); | ||
// test speed of repeated query on an already set up dynamicview | ||
start2 = process.hrtime(); | ||
// start2 = process.hrtime(); | ||
start2 = performance.now(); | ||
var results = dv.data(); | ||
end2 = process.hrtime(start2); | ||
totalTimes2.push(end2); | ||
// end2 = process.hrtime(start2); | ||
end2 = performance.now() - start2; | ||
totalTimes2.push([0, end2 * 1e6]); | ||
samplecoll.removeDynamicView("perfview"); | ||
} | ||
for(var idx=0; idx < totalTimes.length; idx++) { | ||
@@ -251,3 +264,3 @@ totalMS += totalTimes[idx][0] * 1e3 + totalTimes[idx][1]/1e6; | ||
} | ||
totalMS = totalMS.toFixed(2); | ||
@@ -259,3 +272,3 @@ totalMS2 = totalMS2.toFixed(2); | ||
rate2 = rate2.toFixed(2); | ||
console.log("loki dynamic view first find : " + totalMS + "ms (" + rate + " ops/s) " + loopIterations + " iterations"); | ||
@@ -262,0 +275,0 @@ console.log("loki dynamic view subsequent finds : " + totalMS2 + "ms (" + rate2 + " ops/s) " + loopIterations + " iterations"); |
@@ -1,1 +0,2 @@ | ||
!function(t,e){"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?module.exports=e():t.loki=e()}(this,function(){return function(){"use strict";function t(t,e,i){return t===e?i?!0:!1:void 0===t?!0:void 0===e?!1:null===t?!0:null===e?!1:e>t}function e(t,e,i){return t===e?i?!0:!1:void 0===t?!1:void 0===e?!0:null===t?!1:null===e?!0:t>e}function i(i,n,s){return i===n?0:s?t(i,n)?1:-1:e(i,n)?1:-1}function n(t,e){var i,n=e||"parse-stringify";return"parse-stringify"===n&&(i=JSON.parse(JSON.stringify(t))),i}function s(){try{return"localStorage"in window&&null!==window.localStorage}catch(t){return!1}}function r(){}function o(t,e){t.apply(null,e)}function a(t,e){this.filename=t||"loki.db",this.collections=[],this.databaseVersion=1.1,this.engineVersion=1.1,this.autosave=!1,this.autosaveInterval=5e3,this.autosaveHandle=null,this.options={},this.persistenceMethod=null,this.persistenceAdapter=null,this.events={init:[],flushChanges:[],close:[],changes:[],warning:[]};var i=function(){return"undefined"==typeof window?"NODEJS":"undefined"!=typeof global&&global.window?"NODEJS":"undefined"!=typeof document?-1===document.URL.indexOf("http://")&&-1===document.URL.indexOf("https://")?"CORDOVA":"BROWSER":"CORDOVA"};this.ENV=e&&e.hasOwnProperty("env")?e.env:i(),"undefined"===this.ENV&&(this.ENV="NODEJS"),"NODEJS"===this.ENV&&(this.fs=require("fs")),"undefined"!=typeof e&&this.configureOptions(e,!0),this.on("init",this.clearChanges)}function l(t,e,i,n){return this.collection=t,this.searchIsChained=!e&&!i,this.filteredrows=[],this.filterInitialized=!1,"undefined"!=typeof e&&null!==e?this.find(e,n):"undefined"!=typeof i&&null!==i?this.where(i):this}function h(t,e,i){this.collection=t,this.name=e,this.persistent=!1,"undefined"!=typeof i&&(this.persistent=i),this.resultset=new l(t),this.resultdata=[],this.resultsdirty=!1,this.cachedresultset=null,this.filterPipeline=[],this.sortFunction=null,this.sortCriteria=null,this.sortDirty=!1,this.events={rebuild:[]}}function c(t,e){function i(t,e,i){u.changes.push({name:t,operation:e,obj:JSON.parse(JSON.stringify(i))})}function n(){u.changes=[]}function s(t){t&&(t.meta||(t.meta={}),t.meta.created=(new Date).getTime(),t.meta.revision=0)}function r(t){t&&(t.meta.updated=(new Date).getTime(),t.meta.revision+=1)}function o(t){i(u.name,"I",t)}function a(t){i(u.name,"U",t)}function l(t){s(t),o(t)}function h(t){r(t),a(t)}function c(){p=u.disableChangesApi?s:l,y=u.disableChangesApi?r:h}this.name=t,this.data=[],this.idIndex=[],this.binaryIndices={},this.objType=t,this.dirty=!0,this.cachedIndex=null,this.cachedBinaryIndex=null,this.cachedData=null;var u=this;e=e||{},this.transactional=e.hasOwnProperty("transactional")?e.transactional:!1,this.cloneObjects=e.hasOwnProperty("clone")?e.clone:!1,this.asyncListeners=e.hasOwnProperty("asyncListeners")?e.asyncListeners:!1,this.disableChangesApi=e.hasOwnProperty("disableChangesApi")?e.disableChangesApi:!0,this.maxId=0,this.DynamicViews=[],this.events={insert:[],update:[],close:[],flushbuffer:[],error:[],"delete":[],warning:[]},this.changes=[],this.ensureId();var d=[];if(e&&e.indices)if("[object Array]"===Object.prototype.toString.call(e.indices))d=e.indices;else{if("string"!=typeof e.indices)throw new TypeError("Indices needs to be a string or an array of strings");d=[e.indices]}for(var f=0;f<d.length;f++)this.ensureIndex(d[f]);this.getChanges=function(){return u.changes},this.flushChanges=n;var p,y;c(),this.setChangesApi=function(t){u.disableChangesApi=!t,c()},this.on("insert",function(t){p(t)}),this.on("update",function(t){y(t)}),this.on("delete",function(t){u.disableChangesApi||i(u.name,"R",t)}),this.on("warning",console.warn),n()}function u(t,e,i){for(var n,s,r=0,o=t.length;o>r;){if(s=(r+o)/2|0,n=i.apply(null,[e,t[s]]),0==n)return{found:!0,index:s};0>n?o=s:r=s+1}return{found:!1,index:o}}function d(t){return function(e,i){return u(e,i,t)}}function f(){}{var p={copyProperties:function(t,e){var i;for(i in t)e[i]=t[i]}},y={$eq:function(t,e){return t===e},$gt:function(t,i){return e(t,i)},$gte:function(t,i){return e(t,i,!0)},$lt:function(e,i){return t(e,i)},$lte:function(e,i){return t(e,i,!0)},$ne:function(t,e){return t!==e},$regex:function(t,e){return e.test(t)},$in:function(t,e){return e.indexOf(t)>-1},$contains:function(t,e){var i=function(){return!0};return Array.isArray(e)||(e=[e]),Array.isArray(t)?i=function(e){return-1!==t.indexOf(e)}:"string"==typeof t?i=function(e){return-1!==t.indexOf(e)}:t&&"object"==typeof t&&(i=function(e){return t.hasOwnProperty(e)}),e.reduce(function(t,e){return t?i(e):t},!0)}};"object"==typeof exports?require("fs"):!1}return r.prototype.events={},r.prototype.asyncListeners=!1,r.prototype.on=function(t,e){var i=this.events[t];return i||(i=this.events[t]=[]),i.push(e),e},r.prototype.emit=function(t){var e=Array.prototype.slice.call(arguments,0),i=this;if(!t||!this.events[t])throw new Error("No event "+t+" defined");e.splice(0,1),this.events[t].forEach(function(t){i.asyncListeners?setTimeout(function(){o(t,e)},1):o(t,e)})},r.prototype.removeListener=function(t,e){if(this.events[t]){var i=this.events[t];i.splice(i.indexOf(e),1)}},a.prototype=new r,a.prototype.configureOptions=function(t,e){this.options={},"undefined"!=typeof t&&(this.options=t),this.persistenceMethod=null,this.options.hasOwnProperty("persistenceMethod")&&(this.persistenceMethod=t.persistenceMethod),this.persistenceAdapter=null,this.options.hasOwnProperty("adapter")&&(this.persistenceMethod="adapter",this.persistenceAdapter=t.adapter),t.hasOwnProperty("autoload")&&"undefined"!=typeof e&&e&&this.loadDatabase(t,t.autoloadCallback),this.options.hasOwnProperty("autosaveInterval")&&(this.autosaveDisable(),this.autosaveInterval=parseInt(this.options.autosaveInterval)),this.options.hasOwnProperty("autosave")&&this.options.autosave&&(this.autosaveDisable(),this.autosave=!0,this.autosaveEnable())},a.prototype.anonym=function(t,e){var i=new c("anonym",e);return i.insert(t),i},a.prototype.addCollection=function(t,e){var i=new c(t,e);return this.collections.push(i),i},a.prototype.loadCollection=function(t){if(!t.name)throw new Error("Collection must be have a name property to be loaded");this.collections.push(t)},a.prototype.getCollection=function(t){var e,i=this.collections.length;for(e=0;i>e;e+=1)if(this.collections[e].name===t)return this.collections[e];return this.emit("warning","collection "+t+" not found"),null},a.prototype.listCollections=function(){for(var t=this.collections.length,e=[];t--;)e.push({name:this.collections[t].name,type:this.collections[t].objType,count:this.collections[t].data.length});return e},a.prototype.removeCollection=function(t){var e,i=this.collections.length;for(e=0;i>e;e+=1)if(this.collections[e].name===t)return void this.collections.splice(e,1)},a.prototype.getName=function(){return this.name},a.prototype.serializeReplacer=function(t,e){switch(t){case"autosaveHandle":return null;default:return e}},a.prototype.serialize=function(){return JSON.stringify(this,this.serializeReplacer)},a.prototype.toJson=a.prototype.serialize,a.prototype.loadJSON=function(t,e){var i,n,s,r,o=JSON.parse(t),a=0,l=o.collections.length,h=!1;for(this.name=o.name,this.databaseVersion=1,o.hasOwnProperty("databaseVersion")&&(this.databaseVersion=o.databaseVersion),this.databaseVersion!==this.engineVersion&&(h=!0),this.collections=[],a;l>a;a+=1){if(i=o.collections[a],n=this.addCollection(i.name),s=i.data.length,r=0,e&&e.hasOwnProperty(i.name)){var c=e[i.name].inflate?e[i.name].inflate:p.copyProperties;for(r;s>r;r++){var u=new e[i.name].proto;c(i.data[r],u),n.data[r]=u}}else for(r;s>r;r++)n.data[r]=i.data[r];if(h&&1.1==this.engineVersion){if(n.transactional=!1,n.cloneObjects=!1,n.asyncListeners=!0,n.disableChangesApi=!0,console.warn("upgrading database, loki id is now called '$loki' instead of 'id'"),n.data.length>0&&!n.data[0].hasOwnProperty("$loki"))for(var d=n.data.length,f=null,y=0;d>y;y++)f=n.data[y],f.$loki=f.id,delete f.id,f.hasOwnProperty.originalId&&(f.id=f.originalId)}else n.transactional=i.transactional,n.asyncListeners=i.asyncListeners,n.disableChangesApi=i.disableChangesApi,n.cloneObjects=i.cloneObjects;if(n.maxId=0===i.data.length?0:i.maxId,n.idIndex=i.idIndex,"undefined"!=typeof i.indices&&(n.idIndex=i.indices.id),"undefined"!=typeof i.binaryIndices&&(n.binaryIndices=i.binaryIndices),n.ensureId(),"undefined"!=typeof i.DynamicViews)for(var y=0;y<i.DynamicViews.length;y++){var v=i.DynamicViews[y],g=n.addDynamicView(v.name,v.persistent);if(g.resultdata=v.resultdata,g.resultsdirty=v.resultsdirty,g.filterPipeline=v.filterPipeline,h&&"undefined"!=typeof v.sortColumn&&null!=v.sortColumn){var w=!1;"undefined"!=typeof v.sortColumnDesc&&(w=v.sortColumnDesc),g.sortCriteria=[v.sortColumn,w]}else g.sortCriteria=v.sortCriteria;g.sortFunction=null,g.sortDirty=v.sortDirty,g.resultset.filteredrows=v.resultset.filteredrows,g.resultset.searchIsChained=v.resultset.searchIsChained,g.resultset.filterInitialized=v.resultset.filterInitialized,g.rematerialize({removeWhereFilters:!0})}}},a.prototype.close=function(t){this.autosave&&(this.autosaveDisable(),this.autosaveDirty()&&this.saveDatabase()),t&&this.on("close",t),this.emit("close")},a.prototype.generateChangesNotification=function(t){function e(t){return t.name}var i=[],n=t||this.collections.map(e);return this.collections.forEach(function(t){-1!==n.indexOf(e(t))&&(i=i.concat(t.getChanges()))}),i},a.prototype.serializeChanges=function(t){return JSON.stringify(this.generateChangesNotification(t))},a.prototype.clearChanges=function(){this.collections.forEach(function(t){t.flushChanges&&t.flushChanges()})},a.prototype.loadDatabase=function(t,e){var i=e||function(t){if(t)throw t},n=this;if(null!=this.persistenceMethod){if("fs"===this.persistenceMethod&&this.fs.readFile(this.filename,{encoding:"utf8"},function(e,s){return e?i(e,null):(n.loadJSON(s,t||{}),void i(null,s))}),"localStorage"===this.persistenceMethod)if(s()){var r=localStorage.getItem(this.filename);n.loadJSON(r,t||{}),i(null,r)}else i(new Error("localStorage is not available"));return void("adapter"===this.persistenceMethod&&(null!==this.persistenceAdapter?this.persistenceAdapter.loadDatabase(this.filename,function(e){"undefined"==typeof e||null===e?(console.warn("lokijs loadDatabase : Database not found"),i("Database not found")):(n.loadJSON(e,t||{}),i(null))}):i(new Error("persistenceAdapter not configured"))))}if("NODEJS"===this.ENV)this.fs.readFile(this.filename,{encoding:"utf8"},function(e,s){return e?i(e,null):(s.length||(s=n.serialize()),n.loadJSON(s,t||{}),void i(null,s))});else if("BROWSER"===this.ENV)if(s()){var r=localStorage.getItem(this.filename);n.loadJSON(r,t||{}),i(null,r)}else i(new Error("localStorage is not available"));else i(new Error("unknown environment"))},a.prototype.saveDatabase=function(t){var e=t||function(t){if(t)throw t},i=this;return this.autosaveClearFlags(),null!=this.persistenceMethod?("fs"===this.persistenceMethod&&i.fs.writeFile(i.filename,i.serialize(),e),"localStorage"===this.persistenceMethod&&(s()?(localStorage.setItem(i.filename,i.serialize()),e(null)):e(new Error("localStorage is not available"))),void("adapter"===this.persistenceMethod&&(null!==this.persistenceAdapter?this.persistenceAdapter.saveDatabase(this.filename,i.serialize(),function(){e(null)}):e(new Error("persistenceAdapter not configured"))))):void("NODEJS"===this.ENV?i.fs.writeFile(i.filename,i.serialize(),e):"BROWSER"===this.ENV||"CORDOVA"===this.ENV?s()?(localStorage.setItem(i.filename,i.serialize()),e(null)):e(new Error("localStorage is not available")):e(new Error("unknown environment")))},a.prototype.save=a.prototype.saveDatabase,a.prototype.autosaveDirty=function(){for(var t=0;t<this.collections.length;t++)if(this.collections[t].dirty)return!0;return!1},a.prototype.autosaveClearFlags=function(){for(var t=0;t<this.collections.length;t++)this.collections[t].dirty=!1},a.prototype.autosaveEnable=function(){this.autosave=!0;var t=5e3,e=this;"undefined"!=typeof this.autosaveInterval&&null!==this.autosaveInterval&&(t=this.autosaveInterval),this.autosaveHandle=setInterval(function(){e.autosaveDirty()&&e.saveDatabase()},t)},a.prototype.autosaveDisable=function(){"undefined"!=typeof this.autosaveHandle&&null!==this.autosaveHandle&&(clearInterval(this.autosaveHandle),this.autosaveHandle=null)},l.prototype.toJSON=function(){var t=this.copy();return t.collection=null,t},l.prototype.limit=function(t){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));var e=this.copy();return e.filteredrows=e.filteredrows.slice(0,t),e},l.prototype.offset=function(t){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));var e=this.copy();return e.filteredrows=e.filteredrows.splice(t,e.filteredrows.length),e},l.prototype.copy=function(){var t=new l(this.collection,null,null);return t.filteredrows=this.filteredrows.slice(),t.filterInitialized=this.filterInitialized,t},l.prototype.branch=l.prototype.copy,l.prototype.sort=function(t){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));var e=function(t,e){return function(i,n){var s=e.collection.data[i],r=e.collection.data[n];return t(s,r)}}(t,this);return this.filteredrows.sort(e),this},l.prototype.simplesort=function(t,e){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data)),"undefined"==typeof e&&(e=!1);var n=function(t,e,n){return function(s,r){var o=n.collection.data[s],a=n.collection.data[r];return i(o[t],a[t],e)}}(t,e,this);return this.filteredrows.sort(n),this},l.prototype.compoundeval=function(t,e,n){var s=t.length;if(0===s)throw new Error("Invalid call to compoundeval, need at least one property");var r=!1,o=t[0];return"string"!=typeof o&&Array.isArray(o)&&(r=o[1],o=o[0]),e[o]===n[o]?1===s?0:this.compoundeval(t.slice(1),e,n,r):i(e[o],n[o],r)},l.prototype.compoundsort=function(t){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));var e=function(t,e){return function(i,n){var s=e.collection.data[i],r=e.collection.data[n];return e.compoundeval(t,s,r)}}(t,this);return this.filteredrows.sort(e),this},l.prototype.calculateRange=function(i,n,s){var r=this.collection.data,o=this.collection.binaryIndices[n].values,a=0,l=o.length-1,h=null,c=0,u=o.length-1;if(0==r.length)return[0,-1];var d=r[o[a]][n],f=r[o[l]][n];switch(i){case"$eq":if(t(s,d)||e(s,f))return[0,-1];break;case"$gt":if(e(s,f,!0))return[0,-1];break;case"$gte":if(e(s,f))return[0,-1];break;case"$lt":if(t(s,d,!0))return[0,-1];break;case"$lte":if(t(s,d))return[0,-1]}for(;l>a;)h=Math.floor((a+l)/2),t(r[o[h]][n],s)?a=h+1:l=h;for(c=a,a=0,l=o.length-1;l>a;)h=Math.floor((a+l)/2),t(s,r[o[h]][n])?l=h:a=h+1;u=l;var p=r[o[c]][n],y=r[o[u]][n];switch(i){case"$eq":return p!==s?[0,-1]:(y!==s&&u--,[c,u]);case"$gt":return t(y,s,!0)?[0,-1]:[u,r.length-1];case"$gte":return t(p,s)?[0,-1]:[c,r.length-1];case"$lt":return 0===c&&t(p,s)?[0,0]:[0,c-1];case"$lte":return y!==s&&u--,0===u&&t(y,s)?[0,0]:[0,u];default:return[0,r.length-1]}},l.prototype.findOr=function(t){var e=0,i=0,n=null,s=[],r=null;if(this.filterInitialized){for(s=[],i=0;i<t.length;i++)for(r=this.branch(),r.find(t[i]),r.data(),n=r.filteredrows,e=0;e<n.length;e++)-1===s.indexOf(n[e])&&s.push(n[e]);this.filteredrows=s}else for(i=0;i<t.length;i++)for(r=this.collection.chain(),r.find(t[i]),r.data(),n=r.filteredrows,e=0;e<n.length;e++)-1===this.filteredrows.indexOf(n[e])&&this.filteredrows.push(n[e]);return this.filterInitialized=!0,this},l.prototype.findAnd=function(t){for(var e=0;e<t.length;e++)this.find(t[e]);return this},l.prototype.find=function(t,e){if(0===this.collection.data.length)return this.searchIsChained?(this.filteredrows=[],this.filterInitialized=!0,this):[];var i,n,s,r,o,a,l,h,c,u=t||"getAll",d={$eq:y.$eq,$gt:y.$gt,$gte:y.$gte,$lt:y.$lt,$lte:y.$lte,$ne:y.$ne,$regex:y.$regex,$in:y.$in,$contains:y.$contains},f=!1,p=[],v=null,g=!0;e=e||!1;for(r in u){g=!1;break}if(g&&(u="getAll"),"getAll"===u)return this.searchIsChained?(this.filteredrows=Object.keys(this.collection.data),this):this.collection.data;var w=!1;for(r in u)if(u.hasOwnProperty(r)){if(i=r,"$and"===r)return this.searchIsChained?(this.findAnd(u[r]),this):this.collection.chain().findAnd(u[r]).data();if("$or"===r)return this.searchIsChained?(this.findOr(u[r]),this):this.collection.chain().findOr(u[r]).data();if(-1!=r.indexOf(".")&&(w=!0),"object"!=typeof u[r])s="$eq",n=u[r];else{if("object"!=typeof u[r])throw"Do not know what you want to do.";for(o in u[r])u[r].hasOwnProperty(o)&&(s=o,n=u[r][o])}break}if("$regex"===s&&(n=RegExp(n)),null===this.collection.data)throw new TypeError;if((!this.searchIsChained||this.searchIsChained&&!this.filterInitialized)&&"$ne"!==s&&"$regex"!==s&&"$contains"!==s&&"$in"!==s&&this.collection.binaryIndices.hasOwnProperty(i)&&(this.collection.ensureIndex(i),f=!0,v=this.collection.binaryIndices[i]),a=d[s],this.searchIsChained){if(this.filterInitialized){if(f)for(l=v,h=this.filteredrows.length;h--;)a(l[this.filteredrows[h]],n)&&p.push(this.filteredrows[h]);else if(l=this.collection.data,h=this.filteredrows.length,w)for(var m,b;h--;)m=l[this.filteredrows[h]],b=i.split("."),b.forEach(function(t){m=m[t]}),a(m,n)&&p.push(this.filteredrows[h]);else for(;h--;)a(l[this.filteredrows[h]][i],n)&&p.push(this.filteredrows[h]);return this.filteredrows=p,this}if(f){l=this.collection.data;for(var I=this.calculateRange(s,i,n,this),O=I[0];O<=I[1];O++)p.push(v.values[O]);this.filteredrows=p}else if(l=this.collection.data,h=l.length,w)for(var m,b;h--;)m=l[h],b=i.split("."),b.forEach(function(t){m=m[t]}),a(m,n)&&p.push(h);else for(;h--;)a(l[h][i],n)&&p.push(h);return this.filteredrows=p,this.filterInitialized=!0,this}if(f){l=this.collection.data,c=l.length;var I=this.calculateRange(s,i,n,this);if(e)return-1!==I[1]?l[v.values[I[0]]]:[];for(h=I[0];h<=I[1];h++)p.push(l[v.values[h]]);this.filteredrows=p}else{if(l=this.collection.data,h=l.length,e){for(;h--;)if(a(l[h][i],n))return l[h];return[]}if(w)for(var m,b;h--;)m=l[h],b=i.split("."),b.forEach(function(t){m=m[t]}),a(m,n)&&p.push(l[h]);else for(;h--;)a(l[h][i],n)&&p.push(l[h])}return p},l.prototype.where=function(t){var e,i=[];if("function"!=typeof t)throw"Argument is not a stored view or a function";e=t;try{if(this.searchIsChained){if(this.filterInitialized){for(var n=this.filteredrows.length;n--;)e(this.collection.data[this.filteredrows[n]])===!0&&i.push(this.filteredrows[n]);return this.filteredrows=i,this}for(var n=this.collection.data.length;n--;)e(this.collection.data[n])===!0&&i.push(n);return this.filteredrows=i,this.filterInitialized=!0,this}for(var n=this.collection.data.length;n--;)e(this.collection.data[n])===!0&&i.push(this.collection.data[n]);return i}catch(s){throw s}},l.prototype.data=function(){var t=[];if(this.searchIsChained&&!this.filterInitialized){if(0===this.filteredrows.length)return this.collection.data;this.filterInitialized=!0}var e,i=this.collection.data,n=this.filteredrows,s=this.filteredrows.length;for(e=0;s>e;e++)t.push(i[n[e]]);return t},l.prototype.update=function(t){if("function"!=typeof t)throw"Argument is not a function";this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));for(var e=this.filteredrows.length,i=this.collection.data,n=0;e>n;n++)t(i[this.filteredrows[n]]),this.collection.update(i[this.filteredrows[n]]);return this},l.prototype.remove=function(){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));for(var t=this.filteredrows.length,e=0;t>e;e++)this.collection.remove(this.filteredrows[e]);return this.filteredrows=[],this},l.prototype.mapReduce=function(t,e){try{return e(this.data().map(t))}catch(i){throw i}},h.prototype=new r,h.prototype.rematerialize=function(t){var e,i,n;if(t=t||{},this.resultdata=[],this.resultsdirty=!0,this.resultset=new l(this.collection),(this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0),t.hasOwnProperty("removeWhereFilters"))for(e=this.filterPipeline.length,i=e;i--;)"where"===this.filterPipeline[i].type&&(i!==this.filterPipeline.length-1&&(this.filterPipeline[i]=this.filterPipeline[this.filterPipeline.length-1]),this.filterPipeline.length--);var s=this.filterPipeline;for(this.filterPipeline=[],e=s.length,n=0;e>n;n++)this.applyFind(s[n].val);return this.data(),this.emit("rebuild",this),this},h.prototype.branchResultset=function(){return this.resultset.copy()},h.prototype.toJSON=function(){var t=new h(this.collection,this.name,this.persistent);return t.resultset=this.resultset,t.resultdata=[],t.resultsdirty=!0,t.filterPipeline=this.filterPipeline,t.sortFunction=this.sortFunction,t.sortCriteria=this.sortCriteria,t.sortDirty=this.sortDirty,t.collection=null,t},h.prototype.applySort=function(t){return this.sortFunction=t,this.sortCriteria=null,this.resultset.sort(t),this.sortDirty=!1,this},h.prototype.applySimpleSort=function(t,e){return"undefined"==typeof e&&(e=!1),this.sortCriteria=[[t,e]],this.sortFunction=null,this.resultset.simplesort(t,e),this.sortDirty=!1,this},h.prototype.applySortCriteria=function(t){return this.sortCriterial=t,this.sortFunction=null,this.resultset.compoundsort(t),this.sortDirty=!1,this},h.prototype.startTransaction=function(){return this.cachedresultset=this.resultset.copy(),this},h.prototype.commit=function(){return this.cachedresultset=null,this},h.prototype.rollback=function(){return this.resultset=this.cachedresultset,this.persistent&&(this.resultdata=this.resultset.data(),this.emit("rebuild",this)),this},h.prototype.applyFind=function(t){return this.filterPipeline.push({type:"find",val:t}),this.resultset.find(t),(this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0),this.persistent&&(this.resultsdirty=!0),this},h.prototype.applyWhere=function(t){return this.filterPipeline.push({type:"where",val:t}),this.resultset.where(t),(this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0),this.persistent&&(this.resultsdirty=!0),this},h.prototype.data=function(){return this.sortDirty&&(this.sortFunction&&this.resultset.sort(this.sortFunction),this.sortCriteria&&this.resultset.compoundsort(this.sortCriteria),this.sortDirty=!1,this.persistent&&(this.resultsdirty=!0)),this.persistent?(this.resultsdirty&&(this.resultdata=this.resultset.data(),this.resultsdirty=!1,this.emit("rebuild",this)),this.resultdata):(this.resultset.filterInitialized||this.emit("rebuild",this),this.resultset.data())},h.prototype.evaluateDocument=function(t){var e=this.resultset.filteredrows,i=e.indexOf(t),n=e.length,s=new l(this.collection);s.filteredrows=[t],s.filterInitialized=!0;for(var r=0;r<this.filterPipeline.length;r++)switch(this.filterPipeline[r].type){case"find":s.find(this.filterPipeline[r].val);break;case"where":s.where(this.filterPipeline[r].val)}var o=0===s.filteredrows.length?-1:0;return-1!=i||-1!=o?-1===i&&-1!==o?(e.push(t),this.persistent&&this.resultdata.push(this.collection.data[t]),void((this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0))):-1!==i&&-1===o?void(n-1>i?(e[i]=e[n-1],e.length=n-1,this.persistent&&(this.resultdata[i]=this.resultdata[n-1],this.resultdata.length=n-1)):(e.length=n-1,this.persistent&&(this.resultdata.length=n-1))):-1!==i&&-1!==o?(this.persistent&&(this.resultdata[i]=this.collection.data[t]),void((this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0))):void 0:void 0},h.prototype.removeDocument=function(t){var e,i=this.resultset.filteredrows,n=i.indexOf(t),s=i.length;for(-1!==n&&(s-1>n?(i[n]=i[s-1],i.length=s-1,this.persistent&&(this.resultdata[n]=this.resultdata[s-1],this.resultdata.length=s-1)):(i.length=s-1,this.persistent&&(this.resultdata.length=s-1))),s=i.length,e=0;s>e;e++)i[e]>t&&i[e]--},h.prototype.mapReduce=function(t,e){try{return e(this.data().map(t))}catch(i){throw i}},c.prototype=new r,c.prototype.ensureIndex=function(i,n){if("undefined"==typeof n&&(n=!1),null===i||void 0===i)throw"Attempting to set index without an associated property";if(!this.binaryIndices.hasOwnProperty(i)||n||this.binaryIndices[i].dirty){this.binaryIndices[i]={name:i,dirty:!0,values:[]};var s,r=this.data.length,o=0;for(s=this.binaryIndices[i],o;r>o;o+=1)s.values.push(o);var a=function(i,n){return function(s,r){var o=n.data[s],a=n.data[r];return o[i]===a[i]?0:e(o[i],a[i])?1:t(o[i],a[i])?-1:void 0}}(i,this);s.values.sort(a),s.dirty=!1,this.dirty=!0}},c.prototype.ensureAllIndexes=function(t){for(var e=Object.keys(this.binaryIndices),i=e.length;i--;)this.ensureIndex(e[i],t)},c.prototype.flagBinaryIndexesDirty=function(){for(var t=Object.keys(this.binaryIndices),e=t.length;e--;)this.binaryIndices[t[e]].dirty=!0},c.prototype.ensureId=function(){var t=this.data.length,e=0;for(this.idIndex=[],e;t>e;e+=1)this.idIndex.push(this.data[e].$loki)},c.prototype.ensureIdAsync=function(t){this.async(function(){this.ensureId()},t)},c.prototype.addDynamicView=function(t,e){var i=new h(this,t,e);return this.DynamicViews.push(i),i},c.prototype.removeDynamicView=function(t){for(var e=0;e<this.DynamicViews.length;e++)this.DynamicViews[e].name===t&&this.DynamicViews.splice(e,1)},c.prototype.getDynamicView=function(t){for(var e=0;e<this.DynamicViews.length;e++)if(this.DynamicViews[e].name===t)return this.DynamicViews[e];return null},c.prototype.findAndUpdate=function(t,e){var i,n=this.where(t),s=0;try{for(s;s<n.length;s++)i=e(n[s]),this.update(i)}catch(r){this.rollback(),console.error(r.message)}},c.prototype.insert=function(t){if(!t){var e=new Error("Object cannot be null");throw this.emit("error",e),e}var i,n=this,s=Array.isArray(t)?t:[t];return s.forEach(function(t){if("object"!=typeof t)throw new TypeError("Document needs to be an object");i=n.clone?JSON.parse(JSON.stringify(t)):t,"undefined"==typeof i.meta&&(i.meta={revision:0,created:0}),n.add(i),n.emit("insert",i)}),i},c.prototype.clear=function(){this.data=[],this.idIndex=[],this.binaryIndices={},this.cachedIndex=null,this.cachedData=null,this.maxId=0,this.DynamicViews=[],this.dirty=!0},c.prototype.update=function(t){if(Object.keys(this.binaryIndices).length>0&&this.flagBinaryIndexesDirty(),Array.isArray(t)){var e=0,i=t.length;for(e;i>e;e+=1)this.update(t[e])}else{if(!t.hasOwnProperty("$loki"))throw"Trying to update unsynced document. Please save the document first by using insert() or addMany()";try{this.startTransaction();var n,s,r=this.get(t.$loki,!0);if(!r)throw new Error("Trying to update a document not in collection.");n=r[0],s=r[1],this.data[s]=t;for(var o=0;o<this.DynamicViews.length;o++)this.DynamicViews[o].evaluateDocument(s);this.idIndex[s]=n.$loki,this.commit(),this.dirty=!0,this.emit("update",t)}catch(a){throw this.rollback(),console.error(a.message),this.emit("error",a),a}}},c.prototype.add=function(t){var e,i=this.DynamicViews.length;if("object"!=typeof t)throw"Object being added needs to be an object";if(Object.keys(this.binaryIndices).length>0&&this.flagBinaryIndexesDirty(),"undefined"!=typeof t.$loki)throw"Document is already in collection, please use update()";try{this.startTransaction(),this.maxId++;var e;for(isNaN(this.maxId)&&(this.maxId=this.data[this.data.length-1].$loki+1),t.$loki=this.maxId,t.meta.version=0,this.data.push(t),e=0;i>e;e++)this.DynamicViews[e].evaluateDocument(this.data.length-1);return this.idIndex.push(t.$loki),this.commit(),this.dirty=!0,t}catch(n){this.rollback(),console.error(n.message)}},c.prototype.removeWhere=function(t){var e;e="function"==typeof t?this.data.filter(t):new l(this,t);for(var i=e.length;i--;)this.remove(e[i])},c.prototype.removeDataOnly=function(){this.removeWhere(function(){return!0})},c.prototype.remove=function(t){if("number"==typeof t&&(t=this.get(t)),"object"!=typeof t)throw new Error("Parameter is not an object");if(Array.isArray(t)){var e=0,i=t.length;for(e;i>e;e+=1)this.remove(t[e])}else{if(!t.hasOwnProperty("$loki"))throw new Error("Object is not a document stored in the collection");Object.keys(this.binaryIndices).length>0&&this.flagBinaryIndexesDirty();try{this.startTransaction();for(var n=this.get(t.$loki,!0),s=n[1],r=0;r<this.DynamicViews.length;r++)this.DynamicViews[r].removeDocument(s);this.data.splice(s,1),this.idIndex.splice(s,1),this.commit(),this.dirty=!0,this.emit("delete")}catch(o){this.rollback(),console.error(o.message),this.emit("error",o)}}},c.prototype.get=function(t,e){var i=e||!1,n=this.idIndex,s=n.length-1,r=0,o=Math.floor(r+(s-r)/2);if(t="number"==typeof t?t:parseInt(t,10),isNaN(t))throw"Passed id is not an integer";for(;n[r]<n[s];)o=Math.floor((r+s)/2),n[o]<t?r=o+1:s=o;return s===r&&n[r]===t?i?[this.data[r],r]:this.data[r]:null},c.prototype.findOne=function(t){var e=new l(this,t,null,!0);return Array.isArray(e)&&0===e.length?null:e},c.prototype.chain=function(){return new l(this,null,null)},c.prototype.find=function(t){return"undefined"==typeof t&&(t="getAll"),new l(this,t,null)},c.prototype.findOneUnindexed=function(t,e){for(var i,n=this.data.length;n--;)if(this.data[n][t]===e)return i=this.data[n];return null},c.prototype.startTransaction=function(){if(this.transactional){this.cachedData=n(this.data,"parse-stringify"),this.cachedIndex=this.idIndex,this.cachedBinaryIndex=this.binaryIndices;for(var t=0;t<this.DynamicViews.length;t++)this.DynamicViews[t].startTransaction()}},c.prototype.commit=function(){if(this.transactional){this.cachedData=null,this.cachedIndex=null,this.cachedBinaryIndices=null;for(var t=0;t<this.DynamicViews.length;t++)this.DynamicViews[t].commit()}},c.prototype.rollback=function(){if(this.transactional){null!==this.cachedData&&null!==this.cachedIndex&&(this.data=this.cachedData,this.idIndex=this.cachedIndex,this.binaryIndices=this.cachedBinaryIndex);for(var t=0;t<this.DynamicViews.length;t++)this.DynamicViews[t].rollback()}},c.prototype.async=function(t,e){setTimeout(function(){if("function"!=typeof t)throw"Argument passed for async execution is not a function";t(),e()},0)},c.prototype.where=function(t){return new l(this,null,t)},c.prototype.mapReduce=function(t,e){try{return e(this.data.map(t))}catch(i){throw i}},c.prototype.no_op=function(){},f.prototype={keys:[],values:[],sort:function(t,e){return e>t?-1:t>e?1:0},setSort:function(t){this.bs=d(t)},bs:function(){return d(this.sort)},set:function(t,e){var i=this.bs(this.keys,t);i.found?this.values[i.index]=e:(this.keys.splice(i.index,0,t),this.values.splice(i.index,0,e))},get:function(t){return this.values[u(this.keys,t,this.sort).index]}},a.Collection=c,a.KeyValueStore=f,a}()}); | ||
!function(t,e){"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?module.exports=e():t.loki=e()}(this,function(){return function(){"use strict";function t(t,e,i){return t===e?i?!0:!1:void 0===t?!0:void 0===e?!1:null===t?!0:null===e?!1:e>t}function e(t,e,i){return t===e?i?!0:!1:void 0===t?!1:void 0===e?!0:null===t?!1:null===e?!0:t>e}function i(i,n,r){return i===n?0:r?t(i,n)?1:-1:e(i,n)?1:-1}function n(t){return Array.isArray(t)?function(e){return-1!==t.indexOf(e)}:"string"==typeof t?function(e){return-1!==t.indexOf(e)}:t&&"object"==typeof t?function(e){return t.hasOwnProperty(e)}:void 0}function r(t,e){var i,n=e||"parse-stringify";return"parse-stringify"===n&&(i=JSON.parse(JSON.stringify(t))),i}function s(){try{return"localStorage"in window&&null!==window.localStorage}catch(t){return!1}}function o(){}function a(t,e){this.filename=t||"loki.db",this.collections=[],this.databaseVersion=1.1,this.engineVersion=1.1,this.autosave=!1,this.autosaveInterval=5e3,this.autosaveHandle=null,this.options={},this.persistenceMethod=null,this.persistenceAdapter=null,this.events={init:[],flushChanges:[],close:[],changes:[],warning:[]};var i=function(){return"undefined"==typeof window?"NODEJS":"undefined"!=typeof global&&global.window?"NODEJS":"undefined"!=typeof document?-1===document.URL.indexOf("http://")&&-1===document.URL.indexOf("https://")?"CORDOVA":"BROWSER":"CORDOVA"};this.ENV=e&&e.hasOwnProperty("env")?e.env:i(),"undefined"===this.ENV&&(this.ENV="NODEJS"),this.configureOptions(e,!0),this.on("init",this.clearChanges)}function h(){this.fs=require("fs")}function l(){}function c(t,e,i,n){return this.collection=t,this.searchIsChained=!e&&!i,this.filteredrows=[],this.filterInitialized=!1,"undefined"!=typeof e&&null!==e?this.find(e,n):"undefined"!=typeof i&&null!==i?this.where(i):this}function u(t,e,i){this.collection=t,this.name=e,this.persistent=!1,"undefined"!=typeof i&&(this.persistent=i),this.resultset=new c(t),this.resultdata=[],this.resultsdirty=!1,this.cachedresultset=null,this.filterPipeline=[],this.sortFunction=null,this.sortCriteria=null,this.sortDirty=!1,this.events={rebuild:[]}}function f(t,e){function i(t,e,i){u.changes.push({name:t,operation:e,obj:JSON.parse(JSON.stringify(i))})}function n(){u.changes=[]}function r(t){t&&(t.meta||(t.meta={}),t.meta.created=(new Date).getTime(),t.meta.revision=0)}function s(t){t&&(t.meta.updated=(new Date).getTime(),t.meta.revision+=1)}function o(t){i(u.name,"I",t)}function a(t){i(u.name,"U",t)}function h(t){r(t),o(t)}function l(t){s(t),a(t)}function c(){p=u.disableChangesApi?r:h,y=u.disableChangesApi?s:l}this.name=t,this.data=[],this.idIndex=[],this.binaryIndices={},this.constraints={unique:{},exact:{}},this.objType=t,this.dirty=!0,this.cachedIndex=null,this.cachedBinaryIndex=null,this.cachedData=null;var u=this;e=e||{},e.hasOwnProperty("unique")&&e.unique.forEach(function(t){u.constraints.unique[t]={}}),e.hasOwnProperty("exact")&&e.exact.forEach(function(t){u.constraints.exact[t]={}}),this.transactional=e.hasOwnProperty("transactional")?e.transactional:!1,this.cloneObjects=e.hasOwnProperty("clone")?e.clone:!1,this.asyncListeners=e.hasOwnProperty("asyncListeners")?e.asyncListeners:!1,this.disableChangesApi=e.hasOwnProperty("disableChangesApi")?e.disableChangesApi:!0,this.maxId=0,this.DynamicViews=[],this.events={insert:[],update:[],"pre-insert":[],"pre-update":[],close:[],flushbuffer:[],error:[],"delete":[],warning:[]},this.changes=[],this.ensureId();var f=[];if(e&&e.indices)if("[object Array]"===Object.prototype.toString.call(e.indices))f=e.indices;else{if("string"!=typeof e.indices)throw new TypeError("Indices needs to be a string or an array of strings");f=[e.indices]}for(var d=0;d<f.length;d++)this.ensureIndex(f[d]);this.getChanges=function(){return u.changes},this.flushChanges=n;var p,y;c(),this.setChangesApi=function(t){u.disableChangesApi=!t,c()},this.on("insert",function(t){p(t)}),this.on("update",function(t){y(t)}),this.on("delete",function(t){u.disableChangesApi||i(u.name,"R",t)}),this.on("warning",console.warn),n()}function d(t){return-1!==t.indexOf(".")}function p(t){return parseFloat(t,10)}function y(t,e){return t+e}function v(t,e){return t-e}function w(t){return t.reduce(y,0)/t.length}function g(t){var e=w(t),i=t.map(function(t){var i=t-e,n=i*i;return n}),n=w(i),r=Math.sqrt(n);return r}function m(t,e,i){if(i===!1)return t[e];for(var n=e.split("."),r=t;n.length>0;)r=r[n.shift()];return r}function b(t,e,i){for(var n,r,s=0,o=t.length;o>s;){if(r=(s+o)/2|0,n=i.apply(null,[e,t[r]]),0===n)return{found:!0,index:r};0>n?o=r:s=r+1}return{found:!1,index:o}}function I(t){return function(e,i){return b(e,i,t)}}function D(){}var x={copyProperties:function(t,e){var i;for(i in t)e[i]=t[i]}},O={$eq:function(t,e){return t===e},$gt:function(t,i){return e(t,i)},$gte:function(t,i){return e(t,i,!0)},$lt:function(e,i){return t(e,i)},$lte:function(e,i){return t(e,i,!0)},$ne:function(t,e){return t!==e},$regex:function(t,e){return e.test(t)},$in:function(t,e){return e.indexOf(t)>-1},$containsAny:function(t,e){var i;return Array.isArray(e)||(e=[e]),i=n(t,e)||function(){return!1},e.reduce(function(t,e){return t?t:i(e)},!1)},$contains:function(t,e){var i;return Array.isArray(e)||(e=[e]),i=n(t,e)||function(){return!0},e.reduce(function(t,e){return t?i(e):t},!0)}},C={$eq:O.$eq,$gt:O.$gt,$gte:O.$gte,$lt:O.$lt,$lte:O.$lte,$ne:O.$ne,$regex:O.$regex,$in:O.$in,$contains:O.$contains,$containsAny:O.$containsAny};return o.prototype.events={},o.prototype.asyncListeners=!1,o.prototype.on=function(t,e){var i=this.events[t];return i||(i=this.events[t]=[]),i.push(e),e},o.prototype.emit=function(t,e){var i=this;if(!t||!this.events[t])throw new Error("No event "+t+" defined");this.events[t].forEach(function(t){i.asyncListeners?setTimeout(function(){t(e)},1):t(e)})},o.prototype.removeListener=function(t,e){if(this.events[t]){var i=this.events[t];i.splice(i.indexOf(e),1)}},a.prototype=new o,a.prototype.configureOptions=function(t,e){var i={NODEJS:"fs",BROWSER:"localStorage",CORDOVA:"localStorage"},n={fs:h,localStorage:l};if(this.options={},this.persistenceMethod=null,this.persistenceAdapter=null,"undefined"!=typeof t){if(this.options=t,this.options.hasOwnProperty("persistenceMethod")&&"function"==typeof n[t.persistenceMethod]&&(this.persistenceMethod=t.persistenceMethod,this.persistenceAdapter=new n[t.persistenceMethod]),this.options.hasOwnProperty("adapter")&&(this.persistenceMethod="adapter",this.persistenceAdapter=t.adapter),t.hasOwnProperty("autoload")&&"undefined"!=typeof e&&e){var r=this;setTimeout(function(){r.loadDatabase(t,t.autoloadCallback)},1)}this.options.hasOwnProperty("autosaveInterval")&&(this.autosaveDisable(),this.autosaveInterval=parseInt(this.options.autosaveInterval,10)),this.options.hasOwnProperty("autosave")&&this.options.autosave&&(this.autosaveDisable(),this.autosave=!0,this.autosaveEnable())}null===this.persistenceAdapter&&(this.persistenceMethod=i[this.ENV],this.persistenceMethod&&(this.persistenceAdapter=new n[this.persistenceMethod]))},a.prototype.anonym=function(t,e){var i=new f("anonym",e);return i.insert(t),i},a.prototype.addCollection=function(t,e){var i=new f(t,e);return this.collections.push(i),i},a.prototype.loadCollection=function(t){if(!t.name)throw new Error("Collection must be have a name property to be loaded");this.collections.push(t)},a.prototype.getCollection=function(t){var e,i=this.collections.length;for(e=0;i>e;e+=1)if(this.collections[e].name===t)return this.collections[e];return this.emit("warning","collection "+t+" not found"),null},a.prototype.listCollections=function(){for(var t=this.collections.length,e=[];t--;)e.push({name:this.collections[t].name,type:this.collections[t].objType,count:this.collections[t].data.length});return e},a.prototype.removeCollection=function(t){var e,i=this.collections.length;for(e=0;i>e;e+=1)if(this.collections[e].name===t)return void this.collections.splice(e,1)},a.prototype.getName=function(){return this.name},a.prototype.serializeReplacer=function(t,e){switch(t){case"autosaveHandle":return null;case"persistenceAdapter":return null;default:return e}},a.prototype.serialize=function(){return JSON.stringify(this,this.serializeReplacer)},a.prototype.toJson=a.prototype.serialize,a.prototype.loadJSON=function(t,e){var i,n,r,s,o=JSON.parse(t),a=0,h=o.collections.length;for(this.name=o.name,this.databaseVersion=1,o.hasOwnProperty("databaseVersion")&&(this.databaseVersion=o.databaseVersion),this.collections=[],a;h>a;a+=1){if(i=o.collections[a],n=this.addCollection(i.name),r=i.data.length,s=0,e&&e.hasOwnProperty(i.name)){var l=e[i.name].inflate?e[i.name].inflate:x.copyProperties;for(s;r>s;s++){var c=new e[i.name].proto;l(i.data[s],c),n.data[s]=c}}else for(s;r>s;s++)n.data[s]=i.data[s];if(n.transactional=i.transactional,n.asyncListeners=i.asyncListeners,n.disableChangesApi=i.disableChangesApi,n.cloneObjects=i.cloneObjects,n.maxId=0===i.data.length?0:i.maxId,n.idIndex=i.idIndex,"undefined"!=typeof i.indices&&(n.idIndex=i.indices.id),"undefined"!=typeof i.binaryIndices&&(n.binaryIndices=i.binaryIndices),n.ensureId(),"undefined"!=typeof i.DynamicViews)for(var u=0;u<i.DynamicViews.length;u++){var f=i.DynamicViews[u],d=n.addDynamicView(f.name,f.persistent);d.resultdata=f.resultdata,d.resultsdirty=f.resultsdirty,d.filterPipeline=f.filterPipeline,d.sortCriteria=f.sortCriteria,d.sortFunction=null,d.sortDirty=f.sortDirty,d.resultset.filteredrows=f.resultset.filteredrows,d.resultset.searchIsChained=f.resultset.searchIsChained,d.resultset.filterInitialized=f.resultset.filterInitialized,d.rematerialize({removeWhereFilters:!0})}}},a.prototype.close=function(t){this.autosave&&(this.autosaveDisable(),this.autosaveDirty()&&this.saveDatabase()),t&&this.on("close",t),this.emit("close")},a.prototype.generateChangesNotification=function(t){function e(t){return t.name}var i=[],n=t||this.collections.map(e);return this.collections.forEach(function(t){-1!==n.indexOf(e(t))&&(i=i.concat(t.getChanges()))}),i},a.prototype.serializeChanges=function(t){return JSON.stringify(this.generateChangesNotification(t))},a.prototype.clearChanges=function(){this.collections.forEach(function(t){t.flushChanges&&t.flushChanges()})},h.prototype.loadDatabase=function(t,e){this.fs.readFile(t,{encoding:"utf8"},function(t,i){e(t?new Error(t):i)})},h.prototype.saveDatabase=function(t,e,i){this.fs.writeFile(t,e,i)},l.prototype.loadDatabase=function(t,e){e(s()?localStorage.getItem(t):new Error("localStorage is not available"))},l.prototype.saveDatabase=function(t,e,i){s()?(localStorage.setItem(t,e),i(null)):i(new Error("localStorage is not available"))},a.prototype.loadDatabase=function(t,e){var i=e||function(t){if(t)throw t},n=this;null!==this.persistenceAdapter?this.persistenceAdapter.loadDatabase(this.filename,function(e){"string"==typeof e?(n.loadJSON(e,t||{}),i(null)):(console.warn("lokijs loadDatabase : Database not found"),i("object"==typeof e?e:"Database not found"))}):i(new Error("persistenceAdapter not configured"))},a.prototype.saveDatabase=function(t){var e=t||function(t){if(t)throw t},i=this;null!==this.persistenceAdapter?this.persistenceAdapter.saveDatabase(this.filename,i.serialize(),function(){i.autosaveClearFlags(),e(null)}):e(new Error("persistenceAdapter not configured"))},a.prototype.save=a.prototype.saveDatabase,a.prototype.autosaveDirty=function(){for(var t=0;t<this.collections.length;t++)if(this.collections[t].dirty)return!0;return!1},a.prototype.autosaveClearFlags=function(){for(var t=0;t<this.collections.length;t++)this.collections[t].dirty=!1},a.prototype.autosaveEnable=function(){this.autosave=!0;var t=5e3,e=this;"undefined"!=typeof this.autosaveInterval&&null!==this.autosaveInterval&&(t=this.autosaveInterval),this.autosaveHandle=setInterval(function(){e.autosaveDirty()&&e.saveDatabase()},t)},a.prototype.autosaveDisable=function(){"undefined"!=typeof this.autosaveHandle&&null!==this.autosaveHandle&&(clearInterval(this.autosaveHandle),this.autosaveHandle=null)},c.prototype.toJSON=function(){var t=this.copy();return t.collection=null,t},c.prototype.limit=function(t){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));var e=this.copy();return e.filteredrows=e.filteredrows.slice(0,t),e},c.prototype.offset=function(t){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));var e=this.copy();return e.filteredrows=e.filteredrows.splice(t,e.filteredrows.length),e},c.prototype.copy=function(){var t=new c(this.collection,null,null);return t.filteredrows=this.filteredrows.slice(),t.filterInitialized=this.filterInitialized,t},c.prototype.branch=c.prototype.copy,c.prototype.sort=function(t){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));var e=function(t,e){return function(i,n){var r=e.collection.data[i],s=e.collection.data[n];return t(r,s)}}(t,this);return this.filteredrows.sort(e),this},c.prototype.simplesort=function(t,e){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data)),"undefined"==typeof e&&(e=!1);var n=function(t,e,n){return function(r,s){var o=n.collection.data[r],a=n.collection.data[s];return i(o[t],a[t],e)}}(t,e,this);return this.filteredrows.sort(n),this},c.prototype.compoundeval=function(t,e,n){var r=t.length;if(0===r)throw new Error("Invalid call to compoundeval, need at least one property");var s=!1,o=t[0];return"string"!=typeof o&&Array.isArray(o)&&(s=o[1],o=o[0]),e[o]===n[o]?1===r?0:this.compoundeval(t.slice(1),e,n,s):i(e[o],n[o],s)},c.prototype.compoundsort=function(t){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));var e=function(t,e){return function(i,n){var r=e.collection.data[i],s=e.collection.data[n];return e.compoundeval(t,r,s)}}(t,this);return this.filteredrows.sort(e),this},c.prototype.calculateRange=function(i,n,r){var s=this.collection.data,o=this.collection.binaryIndices[n].values,a=0,h=o.length-1,l=null,c=0,u=o.length-1;if(0===s.length)return[0,-1];var f=s[o[a]][n],d=s[o[h]][n];switch(i){case"$eq":if(t(r,f)||e(r,d))return[0,-1];break;case"$gt":if(e(r,d,!0))return[0,-1];break;case"$gte":if(e(r,d))return[0,-1];break;case"$lt":if(t(r,f,!0))return[0,-1];break;case"$lte":if(t(r,f))return[0,-1]}for(;h>a;)l=Math.floor((a+h)/2),t(s[o[l]][n],r)?a=l+1:h=l;for(c=a,a=0,h=o.length-1;h>a;)l=Math.floor((a+h)/2),t(r,s[o[l]][n])?h=l:a=l+1;u=h;var p=s[o[c]][n],y=s[o[u]][n];switch(i){case"$eq":return p!==r?[0,-1]:(y!==r&&u--,[c,u]);case"$gt":return t(y,r,!0)?[0,-1]:[u,s.length-1];case"$gte":return t(p,r)?[0,-1]:[c,s.length-1];case"$lt":return 0===c&&t(p,r)?[0,0]:[0,c-1];case"$lte":return y!==r&&u--,0===u&&t(y,r)?[0,0]:[0,u];default:return[0,s.length-1]}},c.prototype.findOr=function(t){var e=0,i=0,n=null,r=[],s=null;if(this.filterInitialized){for(r=[],i=0;i<t.length;i++)for(s=this.branch(),s.find(t[i]),s.data(),n=s.filteredrows,e=0;e<n.length;e++)-1===r.indexOf(n[e])&&r.push(n[e]);this.filteredrows=r}else for(i=0;i<t.length;i++)for(s=this.collection.chain(),s.find(t[i]),s.data(),n=s.filteredrows,e=0;e<n.length;e++)-1===this.filteredrows.indexOf(n[e])&&this.filteredrows.push(n[e]);return this.filterInitialized=!0,this},c.prototype.findAnd=function(t){for(var e=0;e<t.length;e++)this.find(t[e]);return this},c.prototype.dotSubScan=function(t,e,i,n){var r,s,o,a=null,h=e.split(".");for(r=0;r<h.length;r++)if(o=h[r],a){for(s=0;s<a.length;s++)if(i(a[s][o],n))return!0}else t=t[o],Array.isArray(t)&&(a=t);return i(t,n)},c.prototype.find=function(t,e){if(0===this.collection.data.length)return this.searchIsChained?(this.filteredrows=[],this.filterInitialized=!0,this):[];var i,n,r,s,o,a,h,l,c=t||"getAll",u=!1,f=[],d=null,p=!0;e=e||!1;for(s in c){p=!1;break}if(p&&(c="getAll"),"getAll"===c)return this.searchIsChained?(this.filteredrows=Object.keys(this.collection.data),this):this.collection.data;var y=!1;for(s in c)if(c.hasOwnProperty(s)){if(i=s,"$and"===s)return this.searchIsChained?(this.findAnd(c[s]),e&&this.filteredrows.length>1&&(this.filteredrows=this.filteredrows.slice(0,1)),this):(f=this.collection.chain().findAnd(c[s]).data(),e?0===f.length?[]:f[0]:f);if("$or"===s)return this.searchIsChained?(this.findOr(c[s]),e&&this.filteredrows.length>1&&(this.filteredrows=this.filteredrows.slice(0,1)),this):(f=this.collection.chain().findOr(c[s]).data(),e?0===f.length?[]:f[0]:f);if(-1!=s.indexOf(".")&&(y=!0),"object"!=typeof c[s])r="$eq",n=c[s];else{if("object"!=typeof c[s])throw"Do not know what you want to do.";for(o in c[s])c[s].hasOwnProperty(o)&&(r=o,n=c[s][o])}break}if("$regex"===r&&(n=new RegExp(n)),null===this.collection.data)throw new TypeError;if((!this.searchIsChained||this.searchIsChained&&!this.filterInitialized)&&"$ne"!==r&&"$regex"!==r&&"$contains"!==r&&"$containsAny"!==r&&"$in"!==r&&this.collection.binaryIndices.hasOwnProperty(i)&&(this.collection.ensureIndex(i),u=!0,d=this.collection.binaryIndices[i]),a=C[r],this.searchIsChained){if(this.filterInitialized){if(u)for(h=d,l=this.filteredrows.length;l--;)a(h[this.filteredrows[l]],n)&&f.push(this.filteredrows[l]);else if(h=this.collection.data,l=this.filteredrows.length,y)for(;l--;)this.dotSubScan(h[this.filteredrows[l]],i,a,n)&&f.push(this.filteredrows[l]);else for(;l--;)a(h[this.filteredrows[l]][i],n)&&f.push(this.filteredrows[l]);return this.filteredrows=f,this}if(u){h=this.collection.data;for(var v=this.calculateRange(r,i,n,this),w=v[0];w<=v[1];w++)f.push(d.values[w]);this.filteredrows=f}else if(h=this.collection.data,l=h.length,y)for(;l--;)this.dotSubScan(h[l],i,a,n)&&f.push(l);else for(;l--;)a(h[l][i],n)&&f.push(l);return this.filteredrows=f,this.filterInitialized=!0,this}if(u){h=this.collection.data;var v=this.calculateRange(r,i,n,this);if(e)return-1!==v[1]?h[d.values[v[0]]]:[];for(l=v[0];l<=v[1];l++)f.push(h[d.values[l]]);this.filteredrows=f}else{if(h=this.collection.data,l=h.length,e){for(;l--;)if(a(h[l][i],n))return h[l];return[]}if(y)for(;l--;)this.dotSubScan(h[l],i,a,n)&&f.push(h[l]);else for(;l--;)a(h[l][i],n)&&f.push(h[l])}return f},c.prototype.where=function(t){var e,i=[];if("function"!=typeof t)throw"Argument is not a stored view or a function";e=t;try{if(this.searchIsChained){if(this.filterInitialized){for(var n=this.filteredrows.length;n--;)e(this.collection.data[this.filteredrows[n]])===!0&&i.push(this.filteredrows[n]);return this.filteredrows=i,this}for(var n=this.collection.data.length;n--;)e(this.collection.data[n])===!0&&i.push(n);return this.filteredrows=i,this.filterInitialized=!0,this}for(var n=this.collection.data.length;n--;)e(this.collection.data[n])===!0&&i.push(this.collection.data[n]);return i}catch(r){throw r}},c.prototype.data=function(){var t=[];if(this.searchIsChained&&!this.filterInitialized){if(0===this.filteredrows.length)return this.collection.data;this.filterInitialized=!0}var e,i=this.collection.data,n=this.filteredrows,r=this.filteredrows.length;for(e=0;r>e;e++)t.push(i[n[e]]);return t},c.prototype.update=function(t){if("function"!=typeof t)throw"Argument is not a function";this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));for(var e=this.filteredrows.length,i=this.collection.data,n=0;e>n;n++)t(i[this.filteredrows[n]]),this.collection.update(i[this.filteredrows[n]]);return this},c.prototype.remove=function(){this.searchIsChained&&!this.filterInitialized&&0===this.filteredrows.length&&(this.filteredrows=Object.keys(this.collection.data));for(var t=this.filteredrows.length,e=0;t>e;e++)this.collection.remove(this.filteredrows[e]);return this.filteredrows=[],this},c.prototype.mapReduce=function(t,e){try{return e(this.data().map(t))}catch(i){throw i}},c.prototype.eqJoin=function(t,e,i,n){var r,s,o,a=[],h=[],l=[],u="function"==typeof e,d="function"==typeof i,p={};if(a=this.data(),r=a.length,t instanceof c)h=t.data();else{if(!Array.isArray(t))throw new TypeError("joinData needs to be an array or result set");h=t}s=h.length;for(var y=0;s>y;y++)o=d?i(h[y]):h[y][i],p[o]=h[y];n||(n=function(t,e){return{left:t,right:e}});for(var y=0;r>y;y++)o=u?e(a[y]):a[y][e],l.push(n(a[y],p[o]||{}));return this.collection=new f("joinData"),this.collection.insert(l),this.filteredrows=[],this.filterInitialized=!1,this},c.prototype.map=function(t){var e=this.data().map(t);return this.collection=new f("mappedData"),this.collection.insert(e),this.filteredrows=[],this.filterInitialized=!1,this},u.prototype=new o,u.prototype.rematerialize=function(t){var e,i,n;if(t=t||{},this.resultdata=[],this.resultsdirty=!0,this.resultset=new c(this.collection),(this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0),t.hasOwnProperty("removeWhereFilters"))for(e=this.filterPipeline.length,i=e;i--;)"where"===this.filterPipeline[i].type&&(i!==this.filterPipeline.length-1&&(this.filterPipeline[i]=this.filterPipeline[this.filterPipeline.length-1]),this.filterPipeline.length--);var r=this.filterPipeline;for(this.filterPipeline=[],e=r.length,n=0;e>n;n++)this.applyFind(r[n].val);return this.data(),this.emit("rebuild",this),this},u.prototype.branchResultset=function(){return this.resultset.copy()},u.prototype.toJSON=function(){var t=new u(this.collection,this.name,this.persistent);return t.resultset=this.resultset,t.resultdata=[],t.resultsdirty=!0,t.filterPipeline=this.filterPipeline,t.sortFunction=this.sortFunction,t.sortCriteria=this.sortCriteria,t.sortDirty=this.sortDirty,t.collection=null,t},u.prototype.applySort=function(t){return this.sortFunction=t,this.sortCriteria=null,this.queueSortPhase(),this},u.prototype.applySimpleSort=function(t,e){return"undefined"==typeof e&&(e=!1),this.sortCriteria=[[t,e]],this.sortFunction=null,this.queueSortPhase(),this},u.prototype.applySortCriteria=function(t){return this.sortCriterial=t,this.sortFunction=null,this.queueSortPhase(),this},u.prototype.startTransaction=function(){return this.cachedresultset=this.resultset.copy(),this},u.prototype.commit=function(){return this.cachedresultset=null,this},u.prototype.rollback=function(){return this.resultset=this.cachedresultset,this.persistent&&(this.resultdata=this.resultset.data(),this.emit("rebuild",this)),this},u.prototype.applyFind=function(t){return this.filterPipeline.push({type:"find",val:t}),this.resultset.find(t),(this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0,this.queueSortPhase()),this.persistent&&(this.resultsdirty=!0,this.queueSortPhase()),this},u.prototype.applyWhere=function(t){return this.filterPipeline.push({type:"where",val:t}),this.resultset.where(t),(this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0,this.queueSortPhase()),this.persistent&&(this.resultsdirty=!0,this.queueSortPhase()),this},u.prototype.data=function(){return(this.sortDirty||this.resultsdirty||!this.resultset.filterInitialized)&&this.performSortPhase(),this.persistent?this.resultdata:this.resultset.data()},u.prototype.queueSortPhase=function(){var t=this;this.sortDirty||(this.sortDirty=!0,setTimeout(function(){t.performSortPhase()},1))},u.prototype.performSortPhase=function(){if(this.sortDirty||this.resultsdirty||!this.resultset.filterInitialized){if(this.sortFunction&&this.resultset.sort(this.sortFunction),this.sortCriteria&&this.resultset.compoundsort(this.sortCriteria),!this.persistent)return void(this.sortDirty=!1);this.resultdata=this.resultset.data(),this.resultsdirty=!1,this.sortDirty=!1,this.emit("rebuild",this)}},u.prototype.evaluateDocument=function(t){var e=this.resultset.filteredrows,i=e.indexOf(t),n=e.length,r=new c(this.collection);r.filteredrows=[t],r.filterInitialized=!0;for(var s=0;s<this.filterPipeline.length;s++)switch(this.filterPipeline[s].type){case"find":r.find(this.filterPipeline[s].val);break;case"where":r.where(this.filterPipeline[s].val)}var o=0===r.filteredrows.length?-1:0;return-1!=i||-1!=o?-1===i&&-1!==o?(e.push(t),this.persistent&&this.resultdata.push(this.collection.data[t]),void((this.sortFunction||this.sortCriteria)&&this.queueSortPhase())):-1!==i&&-1===o?(n-1>i?(e[i]=e[n-1],e.length=n-1,this.persistent&&(this.resultdata[i]=this.resultdata[n-1],this.resultdata.length=n-1)):(e.length=n-1,this.persistent&&(this.resultdata.length=n-1)),void((this.sortFunction||this.sortCriteria)&&this.queueSortPhase())):-1!==i&&-1!==o?(this.persistent&&(this.resultdata[i]=this.collection.data[t]),void((this.sortFunction||this.sortCriteria)&&(this.sortDirty=!0))):void 0:void 0},u.prototype.removeDocument=function(t){var e,i=this.resultset.filteredrows,n=i.indexOf(t),r=i.length;for(-1!==n&&(r-1>n?(i[n]=i[r-1],i.length=r-1,this.persistent&&(this.resultdata[n]=this.resultdata[r-1],this.resultdata.length=r-1)):(i.length=r-1,this.persistent&&(this.resultdata.length=r-1)),(this.sortFunction||this.sortCriteria)&&this.queueSortPhase()),r=i.length,e=0;r>e;e++)i[e]>t&&i[e]--},u.prototype.mapReduce=function(t,e){try{return e(this.data().map(t))}catch(i){throw i}},f.prototype=new o,f.prototype.ensureIndex=function(i,n){if("undefined"==typeof n&&(n=!1),null===i||void 0===i)throw"Attempting to set index without an associated property";if(!this.binaryIndices.hasOwnProperty(i)||n||this.binaryIndices[i].dirty){this.binaryIndices[i]={name:i,dirty:!0,values:[]};var r,s=this.data.length,o=0;for(r=this.binaryIndices[i],o;s>o;o+=1)r.values.push(o);var a=function(i,n){return function(r,s){var o=n.data[r],a=n.data[s];return o[i]===a[i]?0:e(o[i],a[i])?1:t(o[i],a[i])?-1:void 0}}(i,this);r.values.sort(a),r.dirty=!1,this.dirty=!0}},f.prototype.ensureAllIndexes=function(t){for(var e=Object.keys(this.binaryIndices),i=e.length;i--;)this.ensureIndex(e[i],t)},f.prototype.flagBinaryIndexesDirty=function(){for(var t=Object.keys(this.binaryIndices),e=t.length;e--;)this.binaryIndices[t[e]].dirty=!0},f.prototype.ensureId=function(){var t=this.data.length,e=0;for(this.idIndex=[],e;t>e;e+=1)this.idIndex.push(this.data[e].$loki)},f.prototype.ensureIdAsync=function(t){this.async(function(){this.ensureId()},t)},f.prototype.addDynamicView=function(t,e){var i=new u(this,t,e);return this.DynamicViews.push(i),i},f.prototype.removeDynamicView=function(t){for(var e=0;e<this.DynamicViews.length;e++)this.DynamicViews[e].name===t&&this.DynamicViews.splice(e,1)},f.prototype.getDynamicView=function(t){for(var e=0;e<this.DynamicViews.length;e++)if(this.DynamicViews[e].name===t)return this.DynamicViews[e];return null},f.prototype.findAndUpdate=function(t,e){var i,n=this.where(t),r=0;try{for(r;r<n.length;r++)i=e(n[r]),this.update(i)}catch(s){this.rollback(),console.error(s.message)}},f.prototype.insert=function(t){if(!t){var e=new Error("Object cannot be null");throw this.emit("error",e),e}var i,n=this,r=Array.isArray(t)?t:[t];return r.forEach(function(t){if("object"!=typeof t)throw new TypeError("Document needs to be an object");return i=n.clone?JSON.parse(JSON.stringify(t)):t,"undefined"==typeof i.meta&&(i.meta={revision:0,created:0}),n.emit("pre-insert",i),n.add(i)?void n.emit("insert",i):void 0}),i},f.prototype.clear=function(){this.data=[],this.idIndex=[],this.binaryIndices={},this.cachedIndex=null,this.cachedData=null,this.maxId=0,this.DynamicViews=[],this.dirty=!0},f.prototype.update=function(t){if(Object.keys(this.binaryIndices).length>0&&this.flagBinaryIndexesDirty(),Array.isArray(t)){var e=0,i=t.length;for(e;i>e;e+=1)this.update(t[e])}else{if(!t.hasOwnProperty("$loki"))throw"Trying to update unsynced document. Please save the document first by using insert() or addMany()";try{this.startTransaction();var n,r,s=this.get(t.$loki,!0);if(!s)throw new Error("Trying to update a document not in collection.");this.emit("pre-update",t),n=s[0],r=s[1],this.data[r]=t;for(var o=0;o<this.DynamicViews.length;o++)this.DynamicViews[o].evaluateDocument(r);this.idIndex[r]=n.$loki,this.commit(),this.dirty=!0,this.emit("update",t)}catch(a){throw this.rollback(),console.error(a.message),this.emit("error",a),a}}},f.prototype.add=function(t){var e,i=this.DynamicViews.length;if("object"!=typeof t)throw"Object being added needs to be an object";if(Object.keys(this.binaryIndices).length>0&&this.flagBinaryIndexesDirty(),"undefined"!=typeof t.$loki)throw"Document is already in collection, please use update()";try{this.startTransaction(),this.maxId++;var e;isNaN(this.maxId)&&(this.maxId=this.data[this.data.length-1].$loki+1),t.$loki=this.maxId,t.meta.version=0,this.data.push(t);var n=this;for(Object.keys(n.constraints.unique).forEach(function(e){if(t.hasOwnProperty(e)){if(n.constraints.unique[e][t[e]])throw n.emit("error","Duplicate key for key "+e+" (value "+t[e]+" + already in collection)"),n.data.pop(),new Error("Duplicate key for property "+e);n.constraints.unique[e][t[e]]=t}}),e=0;i>e;e++)this.DynamicViews[e].evaluateDocument(this.data.length-1);return this.idIndex.push(t.$loki),this.commit(),this.dirty=!0,t}catch(r){this.rollback(),console.error(r.message)}},f.prototype.removeWhere=function(t){var e;e="function"==typeof t?this.data.filter(t):new c(this,t);for(var i=e.length;i--;)this.remove(e[i])},f.prototype.removeDataOnly=function(){this.removeWhere(function(){return!0})},f.prototype.remove=function(t){if("number"==typeof t&&(t=this.get(t)),"object"!=typeof t)throw new Error("Parameter is not an object");if(Array.isArray(t)){var e=0,i=t.length;for(e;i>e;e+=1)this.remove(t[e])}else{if(!t.hasOwnProperty("$loki"))throw new Error("Object is not a document stored in the collection");Object.keys(this.binaryIndices).length>0&&this.flagBinaryIndexesDirty();try{this.startTransaction();var n=this.get(t.$loki,!0),r=n[1],s=this;Object.keys(this.constraints.unique).forEach(function(e){s.constraints.unique[e][t[e]]=null,delete s.constraints.unique[e][t[e]]});for(var o=0;o<this.DynamicViews.length;o++)this.DynamicViews[o].removeDocument(r);this.data.splice(r,1),this.idIndex.splice(r,1),this.commit(),this.dirty=!0,this.emit("delete")}catch(a){this.rollback(),console.error(a.message),this.emit("error",a)}}},f.prototype.get=function(t,e){var i=e||!1,n=this.idIndex,r=n.length-1,s=0,o=Math.floor(s+(r-s)/2);if(t="number"==typeof t?t:parseInt(t,10),isNaN(t))throw"Passed id is not an integer";for(;n[s]<n[r];)o=Math.floor((s+r)/2),n[o]<t?s=o+1:r=o;return r===s&&n[s]===t?i?[this.data[s],s]:this.data[s]:null},f.prototype.by=function(t,e){var i;return e?this.constraints.unique[t]&&this.constraints.unique[t][e]?this.constraints.unique[t][e]:void 0:(i=this,function(e){return i.by(t,e)})},f.prototype.findOne=function(t){var e=new c(this,t,null,!0);return Array.isArray(e)&&0===e.length?null:e},f.prototype.chain=function(){return new c(this,null,null)},f.prototype.find=function(t){return"undefined"==typeof t&&(t="getAll"),new c(this,t,null)},f.prototype.findOneUnindexed=function(t,e){for(var i,n=this.data.length;n--;)if(this.data[n][t]===e)return i=this.data[n];return null},f.prototype.startTransaction=function(){if(this.transactional){this.cachedData=r(this.data,"parse-stringify"),this.cachedIndex=this.idIndex,this.cachedBinaryIndex=this.binaryIndices;for(var t=0;t<this.DynamicViews.length;t++)this.DynamicViews[t].startTransaction()}},f.prototype.commit=function(){if(this.transactional){this.cachedData=null,this.cachedIndex=null,this.cachedBinaryIndices=null;for(var t=0;t<this.DynamicViews.length;t++)this.DynamicViews[t].commit()}},f.prototype.rollback=function(){if(this.transactional){null!==this.cachedData&&null!==this.cachedIndex&&(this.data=this.cachedData,this.idIndex=this.cachedIndex,this.binaryIndices=this.cachedBinaryIndex);for(var t=0;t<this.DynamicViews.length;t++)this.DynamicViews[t].rollback()}},f.prototype.async=function(t,e){setTimeout(function(){if("function"!=typeof t)throw"Argument passed for async execution is not a function";t(),e()},0)},f.prototype.where=function(t){return new c(this,null,t)},f.prototype.mapReduce=function(t,e){try{return e(this.data.map(t))}catch(i){throw i}},f.prototype.eqJoin=function(t,e,i,n){return new c(this).eqJoin(t,e,i,n)},f.prototype.no_op=function(){},f.prototype.extract=function(t){var e=0,i=this.data.length,n=d(t),r=[]; | ||
for(e;i>e;e+=1)r.push(m(this.data[e],t,n));return r},f.prototype.max=function(t){return Math.max.apply(null,this.extract(t))},f.prototype.min=function(t){return Math.min.apply(null,this.extract(t))},f.prototype.maxRecord=function(t){var e=0,i=this.data.length,n=d(t),r={index:0,value:void 0},s=void 0;for(e;i>e;e+=1)void 0!==s?s<m(this.data[e],t,n)&&(s=m(this.data[e],t,n),r.index=this.data[e].$loki):(s=m(this.data[e],t,n),r.index=this.data[e].$loki);return r.value=s,r},f.prototype.minRecord=function(t){var e=0,i=this.data.length,n=d(t),r={index:0,value:void 0},s=void 0;for(e;i>e;e+=1)void 0!==s?s>m(this.data[e],t,n)&&(s=m(this.data[e],t,n),r.index=this.data[e].$loki):(s=m(this.data[e],t,n),r.index=this.data[e].$loki);return r.value=s,r},f.prototype.extractNumerical=function(t){return this.extract(t).map(p).filter(Number).filter(function(t){return!isNaN(t)})},f.prototype.avg=function(t){return w(this.extractNumerical(t))},f.prototype.stdDev=function(t){return g(this.extractNumerical(t))},f.prototype.mode=function(t){var e={},i=this.extract(t);i.forEach(function(t){e[t]?e[t]+=1:e[t]=1});var n,r,s=void 0;for(n in e)s?s<e[n]&&(r=n):(r=n,s=e[n]);return r},f.prototype.median=function(t){var e=this.extractNumerical(t);e.sort(v);var i=Math.floor(e.length/2);return e.length%2?e[i]:(e[i-1]+e[i])/2},D.prototype={keys:[],values:[],sort:function(t,e){return e>t?-1:t>e?1:0},setSort:function(t){this.bs=new I(t)},bs:function(){return new I(this.sort)},set:function(t,e){var i=this.bs(this.keys,t);i.found?this.values[i.index]=e:(this.keys.splice(i.index,0,t),this.values.splice(i.index,0,e))},get:function(t){return this.values[b(this.keys,t,this.sort).index]}},a.Collection=f,a.KeyValueStore=D,a}()}); |
{ | ||
"name": "lokijs", | ||
"version": "1.2.3", | ||
"version": "1.2.4", | ||
"description": "Fast document oriented javascript in-memory database", | ||
@@ -24,3 +24,3 @@ "homepage": "http://lokijs.org", | ||
"scripts": { | ||
"test": "make test && istanbul cover tests/" | ||
"test": "karma start karma.conf.js --single-run" | ||
}, | ||
@@ -43,3 +43,8 @@ "author": "Joe Minichino <joe.minichino@gmail.com>", | ||
"istanbul": "^0.3.2", | ||
"karma": "^0.12.31", | ||
"karma-cli": "0.0.4", | ||
"karma-jasmine": "^0.3.5", | ||
"karma-phantomjs-launcher": "^0.1.4", | ||
"mocha": "^2.0.1", | ||
"phantomjs": "^1.9.16", | ||
"should": "^4.3.0", | ||
@@ -46,0 +51,0 @@ "uglify-js": "^2.4.15" |
# LokiJS | ||
[![Join the chat at https://gitter.im/techfort/LokiJS](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/techfort/LokiJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
![alt CI-badge](https://travis-ci.org/techfort/LokiJS.svg?branch=master) | ||
[![npm version](https://badge.fury.io/js/lokijs.svg)](http://badge.fury.io/js/lokijs) | ||
[![alt packagequality](http://npm.packagequality.com/shield/lokijs.svg)](http://packagequality.com/#?package=lokijs) | ||
@@ -19,11 +22,11 @@ ## Overview | ||
example usage [here](https://github.com/techfort/LokiJS/wiki) | ||
## Demo | ||
## Current state | ||
The following demos are available: | ||
- [Sandbox / Playground] (https://rawgit.com/techfort/LokiJS/master/examples/sandbox/LokiSandbox.htm) | ||
- a node-webkit small demo in the folder demos/desktop_app. You can launch it by running `/path/to/nw demos/desktop_app/' | ||
LokiJS is at version 1.2 [Schnee]. While the roadmap is exciting, LokiJS is at the moment stable. | ||
As LokiJS is written in Javascript it can be run on any environment supporting javascript such as browsers, node.js/node-webkit, hybrid mobile apps (such as phonegap/cordova), or the jvm through engines such as rhino. | ||
## Wiki | ||
Example usage can be found on the [wiki](https://github.com/techfort/LokiJS/wiki) | ||
Made by [@techfort](http://twitter.com/tech_fort), with the precious help of Dave Easterday. [Leave a tip](https://gratipay.com/techfort/) or give us a star if you find LokiJS useful! | ||
### Main Features | ||
@@ -37,2 +40,9 @@ | ||
## Current state | ||
LokiJS is at version 1.2 [Schnee]. While the roadmap is exciting, LokiJS is at the moment stable. | ||
As LokiJS is written in Javascript it can be run on any environment supporting javascript such as browsers, node.js/node-webkit, and hybrid mobile apps (such as phonegap/cordova). | ||
Made by [@techfort](http://twitter.com/tech_fort), with the precious help of Dave Easterday. [Leave a tip](https://gratipay.com/techfort/) or give us a star if you find LokiJS useful! | ||
## Installation | ||
@@ -46,5 +56,3 @@ | ||
## Demo | ||
There's a node-webkit small demo in the folder demos/desktop_app. You can launch it by running `/path/to/nw demos/desktop_app/' | ||
@@ -51,0 +59,0 @@ ## Roadmap |
@@ -1,46 +0,56 @@ | ||
var loki = require('../src/lokijs.js'), | ||
db = new loki(), | ||
gordian = require('gordian'), | ||
suite = new gordian('testEvents'), | ||
options = { | ||
asyncListeners: false, | ||
disableChangesApi: false | ||
}, | ||
users = db.addCollection('users', options), | ||
test = db.addCollection('test', options), | ||
test2 = db.addCollection('test2', options); | ||
// var loki = require('../src/lokijs.js'), | ||
describe('changesApi', function () { | ||
it('does what it says on the tin', function () { | ||
var db = new loki(), | ||
// gordian = require('gordian'), | ||
// suite = new gordian('testEvents'), | ||
options = { | ||
asyncListeners: false, | ||
disableChangesApi: false | ||
}, | ||
users = db.addCollection('users', options), | ||
test = db.addCollection('test', options), | ||
test2 = db.addCollection('test2', options); | ||
var u = users.insert({ | ||
name: 'joe' | ||
}); | ||
u.name = 'jack'; | ||
users.update(u); | ||
test.insert({ | ||
name: 'test' | ||
}); | ||
test2.insert({ | ||
name: 'test2' | ||
}); | ||
var u = users.insert({ | ||
name: 'joe' | ||
}); | ||
u.name = 'jack'; | ||
users.update(u); | ||
test.insert({ | ||
name: 'test' | ||
}); | ||
test2.insert({ | ||
name: 'test2' | ||
}); | ||
var userChanges = db.generateChangesNotification(['users']); | ||
suite.assertEqual('Single collection changes', 2, userChanges.length); | ||
suite.assertEqual('Check serialized changes', db.serializeChanges(['users']), JSON.stringify(userChanges)); | ||
var someChanges = db.generateChangesNotification(['users', 'test2']); | ||
suite.assertEqual('Changes number for selected collections', 3, someChanges.length); | ||
var allChanges = db.generateChangesNotification(); | ||
suite.assertEqual('Changes number for all collections', 4, allChanges.length); | ||
users.setChangesApi(false); | ||
suite.assertEqual('Changes Api disabled', true, users.disableChangesApi); | ||
u.name = 'john'; | ||
users.update(u); | ||
var newChanges = db.generateChangesNotification(['users']); | ||
suite.assertEqual('Change should not register after Api disabled', 2, newChanges.length); | ||
db.clearChanges(); | ||
suite.assertEqual('clearChanges should wipe changes', 0, users.getChanges().length); | ||
var userChanges = db.generateChangesNotification(['users']); | ||
u.name = 'jim'; | ||
users.update(u); | ||
users.flushChanges(); | ||
suite.assertEqual('Collection level changes flush', 0, users.getChanges().length); | ||
expect(userChanges.length).toEqual(2); | ||
expect(db.serializeChanges(['users'])).toEqual(JSON.stringify(userChanges)); | ||
suite.report(); | ||
var someChanges = db.generateChangesNotification(['users', 'test2']); | ||
expect(someChanges.length).toEqual(3); | ||
var allChanges = db.generateChangesNotification(); | ||
expect(allChanges.length).toEqual(4); | ||
users.setChangesApi(false); | ||
expect(users.disableChangesApi).toEqual(true); | ||
u.name = 'john'; | ||
users.update(u); | ||
var newChanges = db.generateChangesNotification(['users']); | ||
expect(newChanges.length).toEqual(2); | ||
db.clearChanges(); | ||
expect(users.getChanges().length).toEqual(0); | ||
u.name = 'jim'; | ||
users.update(u); | ||
users.flushChanges(); | ||
expect(users.getChanges().length).toEqual(0); | ||
}); | ||
}); |
@@ -1,37 +0,36 @@ | ||
var loki = require('../src/lokijs.js'), | ||
db = new loki('test', { | ||
persistenceMethod: null | ||
}), | ||
gordian = require('gordian'), | ||
suite = new gordian('testEvents'), | ||
users = db.addCollection('users', { | ||
asyncListeners: false | ||
}); | ||
// var loki = require('../src/lokijs.js'), | ||
describe('eventEmitter', function () { | ||
var db; | ||
users.insert({ | ||
name: 'joe' | ||
}); | ||
beforeEach(function () { | ||
db = new loki('test', { | ||
persistenceMethod: null | ||
}), | ||
users = db.addCollection('users', { | ||
asyncListeners: false | ||
}); | ||
function testAsync() { | ||
suite.assertEqual('DB events async', db.asyncListeners, false); | ||
} | ||
users.insert({ | ||
name: 'joe' | ||
}); | ||
}); | ||
function testEmit() { | ||
var index = db.on('test', function test(obj) { | ||
suite.assertEqual('Argument passed to event', 42, obj); | ||
it('async', function testAsync() { | ||
expect(db.asyncListeners).toBe(false); | ||
}); | ||
db.emit('test', 42); | ||
db.removeListener('test', index); | ||
it('emit', function () { | ||
var index = db.on('test', function test(obj) { | ||
expect(obj).toEqual(42); | ||
}); | ||
suite.assertEqual('Event has no listeners attached', db.events['test'].length, 0); | ||
db.emit('test', 42); | ||
db.removeListener('test', index); | ||
suite.assertThrows('No event testEvent', function testEvent() { | ||
db.emit('testEvent'); | ||
}, Error); | ||
} | ||
expect(db.events['test'].length).toEqual(0); | ||
testAsync(); | ||
testEmit(); | ||
suite.report(); | ||
expect(function testEvent() { | ||
db.emit('testEvent'); | ||
}).toThrow(new Error('No event testEvent defined')); | ||
}); | ||
}); |
@@ -1,9 +0,10 @@ | ||
require('./test'); | ||
require('./testTyped'); | ||
require('./eventEmitter'); | ||
require('./changesApi'); | ||
require('./testCollection'); | ||
require('./nodePersistence'); | ||
require('./testRemove'); | ||
require('./testCryptedFileAdapter'); | ||
require('./testStats'); | ||
// require('./test'); | ||
//require('./testTyped'); | ||
// require('./eventEmitter'); | ||
// require('./changesApi'); | ||
// require('./testCollection'); | ||
// require('./nodePersistence'); | ||
// require('./testRemove'); | ||
// require('./testCryptedFileAdapter'); | ||
// require('./testStats'); | ||
// require('./joins'); |
@@ -1,40 +0,40 @@ | ||
var loki = require('../src/lokijs.js'), | ||
db = new loki('./loki.json'), | ||
gordian = require('gordian'), | ||
suite = new gordian('nodePersistence'), | ||
users = db.addCollection('users'); | ||
// var loki = require('../src/lokijs.js'), | ||
// db = new loki('./loki.json'), | ||
// gordian = require('gordian'), | ||
// suite = new gordian('nodePersistence'), | ||
// users = db.addCollection('users'); | ||
users.insert([{ | ||
name: 'joe' | ||
}, { | ||
name: 'jack' | ||
}]); | ||
// users.insert([{ | ||
// name: 'joe' | ||
// }, { | ||
// name: 'jack' | ||
// }]); | ||
db.saveDatabase( function reload(){ | ||
// db.saveDatabase( function reload(){ | ||
var reloaded = new loki('./loki.json'); | ||
reloaded.loadDatabase({}, function () { | ||
var users2 = reloaded.getCollection('users'); | ||
suite.assertEqual('There are 2 objects in the reloaded db', 2, users2.data.length); | ||
require('fs').unlink('./loki.json'); | ||
}); | ||
}); | ||
// var reloaded = new loki('./loki.json'); | ||
// reloaded.loadDatabase({}, function () { | ||
// var users2 = reloaded.getCollection('users'); | ||
// suite.assertEqual('There are 2 objects in the reloaded db', 2, users2.data.length); | ||
// require('fs').unlink('./loki.json'); | ||
// }); | ||
// }); | ||
// test autoload callback fires even when database does not exist | ||
function testAutoLoad() { | ||
var cbSuccess = false; | ||
// // test autoload callback fires even when database does not exist | ||
// function testAutoLoad() { | ||
// var cbSuccess = false; | ||
var tdb = new loki('nonexistent.db', | ||
{ | ||
autoload: true, | ||
autoloadCallback : function() { cbSuccess = true; } | ||
}); | ||
// var tdb = new loki('nonexistent.db', | ||
// { | ||
// autoload: true, | ||
// autoloadCallback : function() { cbSuccess = true; } | ||
// }); | ||
setTimeout(function() { | ||
suite.assertEqual('autoload callback was called', cbSuccess, true); | ||
suite.report(); | ||
}, 500); | ||
} | ||
// setTimeout(function() { | ||
// suite.assertEqual('autoload callback was called', cbSuccess, true); | ||
// suite.report(); | ||
// }, 500); | ||
// } | ||
// due to async nature of top inline test, give it some time to complete | ||
setTimeout(testAutoLoad, 500); | ||
// // due to async nature of top inline test, give it some time to complete | ||
// setTimeout(testAutoLoad, 500); |
1352
tests/test.js
// to be run in node | ||
var gordian = require('gordian'), | ||
suite = new gordian('LokiTests'), | ||
loki = require('../src/lokijs.js'), | ||
db, | ||
users; | ||
// var gordian = require('gordian'), | ||
// suite = new gordian('LokiTests'), | ||
// loki = require('../src/lokijs.js'), | ||
describe('loki', function () { | ||
var db, | ||
users, | ||
jonas; | ||
function docCompare(a, b) { | ||
if (a.$loki < b.$loki) return -1; | ||
if (a.$loki > b.$loki) return 1; | ||
function docCompare(a, b) { | ||
if (a.$loki < b.$loki) return -1; | ||
if (a.$loki > b.$loki) return 1; | ||
return 0; | ||
} | ||
return 0; | ||
} | ||
db = new loki('test.json'); | ||
users = db.addCollection('user'); | ||
var jonas = null; | ||
beforeEach(function () { | ||
db = new loki('test.json'); | ||
users = db.addCollection('user'); | ||
function populateTestData() { | ||
users.insert({ | ||
name: 'dave', | ||
age: 25, | ||
lang: 'English' | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 25, | ||
lang: 'English' | ||
}); | ||
users.insert({ | ||
name: 'joe', | ||
age: 39, | ||
lang: 'Italian' | ||
}); | ||
users.insert({ | ||
name: 'joe', | ||
age: 39, | ||
lang: 'Italian' | ||
}); | ||
jonas = users.insert({ | ||
name: 'jonas', | ||
age: 30, | ||
lang: 'Swedish' | ||
}); | ||
}) | ||
jonas = users.insert({ | ||
name: 'jonas', | ||
age: 30, | ||
lang: 'Swedish' | ||
}); | ||
} | ||
describe('core methods', function () { | ||
it('works', function () { | ||
// findOne() | ||
var j = users.findOne({ | ||
'name': 'jonas' | ||
}); | ||
suite.assertStrictEqual("findOne", j.name, 'jonas'); | ||
function testCoreMethods() { | ||
// findOne() | ||
var j = users.findOne({ | ||
'name': 'jonas' | ||
}); | ||
suite.assertStrictEqual("findOne", j.name, 'jonas'); | ||
// find() | ||
var result = users.find({ | ||
'age': { | ||
'$gt': 29 | ||
} | ||
}); | ||
suite.assertStrictEqual("find", result.length, 2); | ||
// find() | ||
var result = users.find({ | ||
'age': { | ||
'$gt': 29 | ||
} | ||
}); | ||
suite.assertStrictEqual("find", result.length, 2); | ||
// $regex test | ||
suite.assertStrictEqual('$regex', users.find({ | ||
"name": { | ||
'$regex': /o/ | ||
} | ||
}).length, 2); | ||
// $regex test | ||
suite.assertStrictEqual('$regex', users.find({ | ||
"name": { | ||
'$regex': /o/ | ||
} | ||
}).length, 2); | ||
// insert() : try inserting existing document (should fail), try adding doc with legacy id column | ||
var collectionLength = users.data.length; | ||
var objDave = users.findOne({ | ||
'name': 'dave' | ||
}); | ||
var wasAdded = true; | ||
try { | ||
users.insert(objDave); | ||
} catch (err) { | ||
wasAdded = false; | ||
} | ||
suite.assertStrictEqual('insert existing document caught', wasAdded, false); | ||
// insert() : try inserting existing document (should fail), try adding doc with legacy id column | ||
var collectionLength = users.data.length; | ||
var objDave = users.findOne({ | ||
'name': 'dave' | ||
}); | ||
var wasAdded = true; | ||
try { | ||
users.insert(objDave); | ||
} catch (err) { | ||
wasAdded = false; | ||
} | ||
suite.assertStrictEqual('insert existing document caught', wasAdded, false); | ||
// our collections are not strongly typed so lets invent some object that has its 'own' id column | ||
var legacyObject = { | ||
id: 999, | ||
first: 'aaa', | ||
last: 'bbb', | ||
city: 'pasadena', | ||
state: 'ca' | ||
} | ||
// our collections are not strongly typed so lets invent some object that has its 'own' id column | ||
var legacyObject = { | ||
id: 999, | ||
first: 'aaa', | ||
last: 'bbb', | ||
city: 'pasadena', | ||
state: 'ca' | ||
} | ||
wasAdded = true; | ||
wasAdded = true; | ||
try { | ||
users.insert(legacyObject); | ||
} catch (err) { | ||
wasAdded = false; | ||
} | ||
try { | ||
users.insert(legacyObject); | ||
} catch (err) { | ||
wasAdded = false; | ||
} | ||
suite.assertStrictEqual('insert legacy document allowed', wasAdded, true); | ||
suite.assertStrictEqual('insert legacy document allowed', wasAdded, true); | ||
// remove object so later queries access valid properties on all objects | ||
if (wasAdded) { | ||
users.remove(legacyObject); // the object itself should have been modified | ||
} | ||
// remove object so later queries access valid properties on all objects | ||
if (wasAdded) { | ||
users.remove(legacyObject); // the object itself should have been modified | ||
} | ||
// update() | ||
legacyObject = { | ||
id: 998, | ||
first: 'aaa', | ||
last: 'bbb', | ||
city: 'pasadena', | ||
state: 'ca' | ||
} | ||
var wasUpdated = true; | ||
// update() | ||
legacyObject = { | ||
id: 998, | ||
first: 'aaa', | ||
last: 'bbb', | ||
city: 'pasadena', | ||
state: 'ca' | ||
} | ||
var wasUpdated = true; | ||
try { | ||
users.update(legacyObject); | ||
} catch (err) { | ||
wasUpdated = false; | ||
} | ||
suite.assertStrictEqual('updating object not in collection should fail', wasUpdated, false); | ||
try { | ||
users.update(legacyObject); | ||
} catch (err) { | ||
wasUpdated = false; | ||
} | ||
suite.assertStrictEqual('updating object not in collection should fail', wasUpdated, false); | ||
// remove() - add some bogus object to remove | ||
var userCount1 = users.data.length; | ||
// remove() - add some bogus object to remove | ||
var userCount1 = users.data.length; | ||
testObject = { | ||
first: 'aaa', | ||
last: 'bbb', | ||
city: 'pasadena', | ||
state: 'ca' | ||
} | ||
testObject = { | ||
first: 'aaa', | ||
last: 'bbb', | ||
city: 'pasadena', | ||
state: 'ca' | ||
} | ||
users.insert(testObject); | ||
users.insert(testObject); | ||
suite.assertStrictEqual('delete test : insert obj to delete', userCount1 + 1, users.data.length); | ||
users.remove(testObject); | ||
suite.assertStrictEqual('delete test : delete', userCount1, users.data.length); | ||
}) | ||
}); | ||
suite.assertStrictEqual('delete test : insert obj to delete', userCount1 + 1, users.data.length); | ||
users.remove(testObject); | ||
suite.assertStrictEqual('delete test : delete', userCount1, users.data.length); | ||
} | ||
describe('calculateRange', function () { | ||
it('works', function () { | ||
var eic = db.addCollection("eic"); | ||
eic.ensureIndex("testid"); | ||
function testCalculateRange() { | ||
var eic = db.addCollection("eic"); | ||
eic.ensureIndex("testid"); | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'hhh', | ||
'testFloat': 5.2 | ||
}); //0 | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'aaa', | ||
'testFloat': 6.2 | ||
}); //1 | ||
eic.insert({ | ||
'testid': 5, | ||
'testString': 'zzz', | ||
'testFloat': 7.2 | ||
}); //2 | ||
eic.insert({ | ||
'testid': 6, | ||
'testString': 'ggg', | ||
'testFloat': 1.2 | ||
}); //3 | ||
eic.insert({ | ||
'testid': 9, | ||
'testString': 'www', | ||
'testFloat': 8.2 | ||
}); //4 | ||
eic.insert({ | ||
'testid': 11, | ||
'testString': 'yyy', | ||
'testFloat': 4.2 | ||
}); //5 | ||
eic.insert({ | ||
'testid': 22, | ||
'testString': 'yyz', | ||
'testFloat': 9.2 | ||
}); //6 | ||
eic.insert({ | ||
'testid': 23, | ||
'testString': 'm', | ||
'testFloat': 2.2 | ||
}); //7 | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'hhh', | ||
'testFloat': 5.2 | ||
}); //0 | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'aaa', | ||
'testFloat': 6.2 | ||
}); //1 | ||
eic.insert({ | ||
'testid': 5, | ||
'testString': 'zzz', | ||
'testFloat': 7.2 | ||
}); //2 | ||
eic.insert({ | ||
'testid': 6, | ||
'testString': 'ggg', | ||
'testFloat': 1.2 | ||
}); //3 | ||
eic.insert({ | ||
'testid': 9, | ||
'testString': 'www', | ||
'testFloat': 8.2 | ||
}); //4 | ||
eic.insert({ | ||
'testid': 11, | ||
'testString': 'yyy', | ||
'testFloat': 4.2 | ||
}); //5 | ||
eic.insert({ | ||
'testid': 22, | ||
'testString': 'yyz', | ||
'testFloat': 9.2 | ||
}); //6 | ||
eic.insert({ | ||
'testid': 23, | ||
'testString': 'm', | ||
'testFloat': 2.2 | ||
}); //7 | ||
var rset = eic.chain(); | ||
rset.find({ | ||
'testid': 1 | ||
}); // force index to be built | ||
var rset = eic.chain(); | ||
rset.find({ | ||
'testid': 1 | ||
}); // force index to be built | ||
// ranges are order of sequence in index not data array positions | ||
// ranges are order of sequence in index not data array positions | ||
var range = rset.calculateRange('$eq', 'testid', 22); | ||
suite.assertEqual('calculateRange $eq', range, [6, 6]); | ||
var range = rset.calculateRange('$eq', 'testid', 22); | ||
suite.assertEqual('calculateRange $eq', range, [6, 6]); | ||
range = rset.calculateRange('$eq', 'testid', 1); | ||
suite.assertEqual('calculateRange $eq multiple', range, [0, 1]); | ||
range = rset.calculateRange('$eq', 'testid', 1); | ||
suite.assertEqual('calculateRange $eq multiple', range, [0, 1]); | ||
range = rset.calculateRange('$eq', 'testid', 7); | ||
suite.assertEqual('calculateRange $eq not found', range, [0, -1]); | ||
range = rset.calculateRange('$eq', 'testid', 7); | ||
suite.assertEqual('calculateRange $eq not found', range, [0, -1]); | ||
range = rset.calculateRange('$gte', 'testid', 23); | ||
suite.assertEqual('calculateRange $gte', range, [7, 7]); | ||
range = rset.calculateRange('$gte', 'testid', 23); | ||
suite.assertEqual('calculateRange $gte', range, [7, 7]); | ||
// reference this new record for future evaluations | ||
eic.insert({ | ||
'testid': 23, | ||
'testString': 'bbb', | ||
'testFloat': 1.9 | ||
}); | ||
// reference this new record for future evaluations | ||
eic.insert({ | ||
'testid': 23, | ||
'testString': 'bbb', | ||
'testFloat': 1.9 | ||
}); | ||
range = rset.calculateRange('$gte', 'testid', 23); | ||
suite.assertEqual('calculateRange $gte', range, [7, 8]); | ||
range = rset.calculateRange('$gte', 'testid', 23); | ||
suite.assertEqual('calculateRange $gte', range, [7, 8]); | ||
range = rset.calculateRange('$gte', 'testid', 24); | ||
suite.assertEqual('calculateRange $gte out of range', range, [0, -1]); | ||
range = rset.calculateRange('$gte', 'testid', 24); | ||
suite.assertEqual('calculateRange $gte out of range', range, [0, -1]); | ||
range = rset.calculateRange('$lte', 'testid', 5); | ||
suite.assertEqual('calculateRange $lte', range, [0, 2]); | ||
range = rset.calculateRange('$lte', 'testid', 5); | ||
suite.assertEqual('calculateRange $lte', range, [0, 2]); | ||
range = rset.calculateRange('$lte', 'testid', 1); | ||
suite.assertEqual('calculateRange $lte', range, [0, 1]); | ||
range = rset.calculateRange('$lte', 'testid', 1); | ||
suite.assertEqual('calculateRange $lte', range, [0, 1]); | ||
range = rset.calculateRange('$lte', 'testid', -1); | ||
suite.assertEqual('calculateRange $lte out of range', range, [0, -1]); | ||
range = rset.calculateRange('$lte', 'testid', -1); | ||
suite.assertEqual('calculateRange $lte out of range', range, [0, -1]); | ||
// add another index on string property | ||
eic.ensureIndex('testString'); | ||
rset.find({ | ||
'testString': 'asdf' | ||
}); // force index to be built | ||
// add another index on string property | ||
eic.ensureIndex('testString'); | ||
rset.find({ | ||
'testString': 'asdf' | ||
}); // force index to be built | ||
range = rset.calculateRange('$lte', 'testString', 'ggg'); | ||
suite.assertEqual('calculateRange $lte string', range, [0, 2]); // includes record added in middle | ||
range = rset.calculateRange('$lte', 'testString', 'ggg'); | ||
suite.assertEqual('calculateRange $lte string', range, [0, 2]); // includes record added in middle | ||
range = rset.calculateRange('$gte', 'testString', 'm'); | ||
suite.assertEqual('calculateRange $gte string', range, [4, 8]); // offset by 1 because of record in middle | ||
range = rset.calculateRange('$gte', 'testString', 'm'); | ||
suite.assertEqual('calculateRange $gte string', range, [4, 8]); // offset by 1 because of record in middle | ||
// add some float range evaluations | ||
eic.ensureIndex('testFloat'); | ||
rset.find({ | ||
'testFloat': '1.1' | ||
}); // force index to be built | ||
// add some float range evaluations | ||
eic.ensureIndex('testFloat'); | ||
rset.find({ | ||
'testFloat': '1.1' | ||
}); // force index to be built | ||
range = rset.calculateRange('$lte', 'testFloat', 1.2); | ||
suite.assertEqual('calculateRange $lte float', range, [0, 0]); | ||
range = rset.calculateRange('$lte', 'testFloat', 1.2); | ||
suite.assertEqual('calculateRange $lte float', range, [0, 0]); | ||
range = rset.calculateRange('$eq', 'testFloat', 1.111); | ||
suite.assertEqual('calculateRange $eq not found', range, [0, -1]); | ||
range = rset.calculateRange('$eq', 'testFloat', 1.111); | ||
suite.assertEqual('calculateRange $eq not found', range, [0, -1]); | ||
range = rset.calculateRange('$eq', 'testFloat', 8.2); | ||
suite.assertEqual('calculateRange $eq found', range, [7, 7]); // 8th pos | ||
range = rset.calculateRange('$eq', 'testFloat', 8.2); | ||
suite.assertEqual('calculateRange $eq found', range, [7, 7]); // 8th pos | ||
range = rset.calculateRange('$gte', 'testFloat', 1.0); | ||
suite.assertEqual('calculateRange $gt all', range, [0, 8]); // 8th pos | ||
}) | ||
}); | ||
range = rset.calculateRange('$gte', 'testFloat', 1.0); | ||
suite.assertEqual('calculateRange $gt all', range, [0, 8]); // 8th pos | ||
} | ||
describe('indexLifecycle', function () { | ||
it('works', function () { | ||
var ilc = db.addCollection('ilc'); | ||
function testIndexLifecycle() { | ||
var ilc = db.addCollection('ilc'); | ||
var hasIdx = ilc.binaryIndices.hasOwnProperty('testid'); | ||
suite.assertEqual('index lifecycle before', hasIdx, false); | ||
var hasIdx = ilc.binaryIndices.hasOwnProperty('testid'); | ||
suite.assertEqual('index lifecycle before', hasIdx, false); | ||
ilc.ensureIndex('testid'); | ||
hasIdx = ilc.binaryIndices.hasOwnProperty('testid'); | ||
suite.assertEqual('index lifecycle created', hasIdx, true); | ||
suite.assertEqual('index lifecycle created', ilc.binaryIndices.testid.dirty, false); | ||
suite.assertEqual('index lifecycle created', ilc.binaryIndices.testid.values, []); | ||
ilc.ensureIndex('testid'); | ||
hasIdx = ilc.binaryIndices.hasOwnProperty('testid'); | ||
suite.assertEqual('index lifecycle created', hasIdx, true); | ||
suite.assertEqual('index lifecycle created', ilc.binaryIndices.testid.dirty, false); | ||
suite.assertEqual('index lifecycle created', ilc.binaryIndices.testid.values, []); | ||
ilc.insert({ | ||
'testid': 5 | ||
}); | ||
suite.assertEqual('index lifecycle dirty', ilc.binaryIndices.testid.dirty, true); | ||
ilc.insert({ | ||
'testid': 8 | ||
}); | ||
suite.assertEqual('index lifecycle still lazy', ilc.binaryIndices.testid.values, []); | ||
suite.assertEqual('index lifecycle still dirty', ilc.binaryIndices.testid.dirty, true); | ||
ilc.insert({ | ||
'testid': 5 | ||
}); | ||
suite.assertEqual('index lifecycle dirty', ilc.binaryIndices.testid.dirty, true); | ||
ilc.insert({ | ||
'testid': 8 | ||
}); | ||
suite.assertEqual('index lifecycle still lazy', ilc.binaryIndices.testid.values, []); | ||
suite.assertEqual('index lifecycle still dirty', ilc.binaryIndices.testid.dirty, true); | ||
ilc.find({ | ||
'testid': 8 | ||
}); // should force index build | ||
suite.assertEqual('index lifecycle built', ilc.binaryIndices.testid.dirty, false); | ||
suite.assertEqual('index lifecycle still lazy', ilc.binaryIndices.testid.values.length, 2); | ||
}) | ||
}) | ||
ilc.find({ | ||
'testid': 8 | ||
}); // should force index build | ||
suite.assertEqual('index lifecycle built', ilc.binaryIndices.testid.dirty, false); | ||
suite.assertEqual('index lifecycle still lazy', ilc.binaryIndices.testid.values.length, 2); | ||
} | ||
describe('indexes', function () { | ||
it('works', function () { | ||
var itc = db.addCollection('test', { | ||
indices: ['testid'] | ||
}); | ||
function testIndexes() { | ||
var itc = db.addCollection('test', { | ||
indices: ['testid'] | ||
}); | ||
itc.insert({ | ||
'testid': 1 | ||
}); | ||
itc.insert({ | ||
'testid': 2 | ||
}); | ||
itc.insert({ | ||
'testid': 5 | ||
}); | ||
itc.insert({ | ||
'testid': 5 | ||
}); | ||
itc.insert({ | ||
'testid': 9 | ||
}); | ||
itc.insert({ | ||
'testid': 11 | ||
}); | ||
itc.insert({ | ||
'testid': 22 | ||
}); | ||
itc.insert({ | ||
'testid': 22 | ||
}); | ||
itc.insert({ | ||
'testid': 1 | ||
}); | ||
itc.insert({ | ||
'testid': 2 | ||
}); | ||
itc.insert({ | ||
'testid': 5 | ||
}); | ||
itc.insert({ | ||
'testid': 5 | ||
}); | ||
itc.insert({ | ||
'testid': 9 | ||
}); | ||
itc.insert({ | ||
'testid': 11 | ||
}); | ||
itc.insert({ | ||
'testid': 22 | ||
}); | ||
itc.insert({ | ||
'testid': 22 | ||
}); | ||
// lte | ||
var results = itc.find({ | ||
'testid': { | ||
'$lte': 1 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $lte', results.length, 1); | ||
// lte | ||
var results = itc.find({ | ||
'testid': { | ||
'$lte': 1 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $lte', results.length, 1); | ||
results = itc.find({ | ||
'testid': { | ||
'$lte': 22 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $lte', results.length, 8); | ||
results = itc.find({ | ||
'testid': { | ||
'$lte': 22 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $lte', results.length, 8); | ||
// lt | ||
results = itc.find({ | ||
'testid': { | ||
'$lt': 1 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $lt', results.length, 0); | ||
// lt | ||
results = itc.find({ | ||
'testid': { | ||
'$lt': 1 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $lt', results.length, 0); | ||
results = itc.find({ | ||
'testid': { | ||
'$lt': 22 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $lt', results.length, 6); | ||
results = itc.find({ | ||
'testid': { | ||
'$lt': 22 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $lt', results.length, 6); | ||
// eq | ||
results = itc.find({ | ||
'testid': { | ||
'$eq': 22 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $eq', results.length, 2); | ||
// eq | ||
results = itc.find({ | ||
'testid': { | ||
'$eq': 22 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $eq', results.length, 2); | ||
// gt | ||
results = itc.find({ | ||
'testid': { | ||
'$gt': 22 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $eq', results.length, 0); | ||
// gt | ||
results = itc.find({ | ||
'testid': { | ||
'$gt': 22 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $eq', results.length, 0); | ||
results = itc.find({ | ||
'testid': { | ||
'$gt': 5 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $eq', results.length, 4); | ||
results = itc.find({ | ||
'testid': { | ||
'$gt': 5 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $eq', results.length, 4); | ||
// gte | ||
results = itc.find({ | ||
'testid': { | ||
'$gte': 5 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $gte', results.length, 6); | ||
// gte | ||
results = itc.find({ | ||
'testid': { | ||
'$gte': 5 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $gte', results.length, 6); | ||
results = itc.find({ | ||
'testid': { | ||
'$gte': 10 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $gte', results.length, 3); | ||
}) | ||
}) | ||
results = itc.find({ | ||
'testid': { | ||
'$gte': 10 | ||
} | ||
}); | ||
suite.assertStrictEqual('find using index $gte', results.length, 3); | ||
} | ||
describe('resultSet', function () { | ||
it('works', function () { | ||
// Resultset find | ||
suite.assertStrictEqual('Resultset (chained) find', users.chain().find({ | ||
'age': { | ||
'$gte': 30 | ||
} | ||
}).where(function (obj) { | ||
return obj.lang === 'Swedish'; | ||
}).data().length, 1); | ||
function testResultset() { | ||
// Resultset find | ||
suite.assertStrictEqual('Resultset (chained) find', users.chain().find({ | ||
'age': { | ||
'$gte': 30 | ||
} | ||
}).where(function (obj) { | ||
return obj.lang === 'Swedish'; | ||
}).data().length, 1); | ||
// Resultset offset | ||
suite.assertStrictEqual('Resultset (chained) offset', users.chain().offset(1).data().length, users.data.length - 1); | ||
// Resultset offset | ||
suite.assertStrictEqual('Resultset (chained) offset', users.chain().offset(1).data().length, users.data.length - 1); | ||
// Resultset limit | ||
suite.assertStrictEqual('Resultset (chained) limit', users.chain().limit(2).data().length, 2); | ||
}) | ||
}) | ||
// Resultset limit | ||
suite.assertStrictEqual('Resultset (chained) limit', users.chain().limit(2).data().length, 2); | ||
describe('andOrOps', function () { | ||
it('works', function () { | ||
var eic = db.addCollection("eic"); | ||
} | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'hhh', | ||
'testFloat': 5.2 | ||
}); //0 | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'bbb', | ||
'testFloat': 6.2 | ||
}); //1 | ||
eic.insert({ | ||
'testid': 5, | ||
'testString': 'zzz', | ||
'testFloat': 7.2 | ||
}); //2 | ||
eic.insert({ | ||
'testid': 6, | ||
'testString': 'ggg', | ||
'testFloat': 1.2 | ||
}); //3 | ||
eic.insert({ | ||
'testid': 9, | ||
'testString': 'www', | ||
'testFloat': 8.2 | ||
}); //4 | ||
eic.insert({ | ||
'testid': 11, | ||
'testString': 'yyy', | ||
'testFloat': 4.2 | ||
}); //5 | ||
eic.insert({ | ||
'testid': 22, | ||
'testString': 'bbb', | ||
'testFloat': 9.2 | ||
}); //6 | ||
eic.insert({ | ||
'testid': 23, | ||
'testString': 'm', | ||
'testFloat': 2.2 | ||
}); //7 | ||
function testAndOrOps() { | ||
var eic = db.addCollection("eic"); | ||
// coll.find $and | ||
suite.assertStrictEqual('$and op test1', eic.find({ | ||
'$and': [{ | ||
'testid': 1 | ||
}, { | ||
'testString': 'bbb' | ||
}] | ||
}).length, 1); | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'hhh', | ||
'testFloat': 5.2 | ||
}); //0 | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'bbb', | ||
'testFloat': 6.2 | ||
}); //1 | ||
eic.insert({ | ||
'testid': 5, | ||
'testString': 'zzz', | ||
'testFloat': 7.2 | ||
}); //2 | ||
eic.insert({ | ||
'testid': 6, | ||
'testString': 'ggg', | ||
'testFloat': 1.2 | ||
}); //3 | ||
eic.insert({ | ||
'testid': 9, | ||
'testString': 'www', | ||
'testFloat': 8.2 | ||
}); //4 | ||
eic.insert({ | ||
'testid': 11, | ||
'testString': 'yyy', | ||
'testFloat': 4.2 | ||
}); //5 | ||
eic.insert({ | ||
'testid': 22, | ||
'testString': 'bbb', | ||
'testFloat': 9.2 | ||
}); //6 | ||
eic.insert({ | ||
'testid': 23, | ||
'testString': 'm', | ||
'testFloat': 2.2 | ||
}); //7 | ||
// resultset.find $and | ||
suite.assertStrictEqual('$and op test2', eic.chain().find({ | ||
'$and': [{ | ||
'testid': 1 | ||
}, { | ||
'testString': 'bbb' | ||
}] | ||
}).data().length, 1); | ||
// coll.find $and | ||
suite.assertStrictEqual('$and op test1', eic.find({ | ||
'$and': [ | ||
{'testid': 1}, | ||
{'testString': 'bbb'} | ||
] | ||
}).length, 1); | ||
// resultset.find explicit operators | ||
suite.assertStrictEqual('$and op test3', eic.chain().find({ | ||
'$and': [{ | ||
'testid': { | ||
'$eq': 1 | ||
} | ||
}, { | ||
'testFloat': { | ||
'$gt': 6.0 | ||
} | ||
}] | ||
}).data().length, 1); | ||
// resultset.find $and | ||
suite.assertStrictEqual('$and op test2', eic.chain().find({ | ||
'$and': [ | ||
{'testid': 1}, | ||
{'testString': 'bbb'} | ||
] | ||
}).data().length, 1); | ||
// coll.find $or | ||
suite.assertStrictEqual('$or op test1', eic.find({ | ||
'$or': [{ | ||
'testid': 1 | ||
}, { | ||
'testString': 'bbb' | ||
}] | ||
}).length, 3); | ||
// resultset.find explicit operators | ||
suite.assertStrictEqual('$and op test3', eic.chain().find({ | ||
'$and': [ | ||
{'testid': {'$eq': 1}}, | ||
{'testFloat': {'$gt': 6.0}} | ||
] | ||
}).data().length, 1); | ||
// resultset.find $or | ||
suite.assertStrictEqual('$or op test2', eic.chain().find({ | ||
'$or': [{ | ||
'testid': 1 | ||
}, { | ||
'testString': 'bbb' | ||
}] | ||
}).data().length, 3); | ||
// coll.find $or | ||
suite.assertStrictEqual('$or op test1', eic.find({ | ||
'$or': [ | ||
{'testid': 1}, | ||
{'testString': 'bbb'} | ||
] | ||
}).length, 3); | ||
// resultset.find explicit operators | ||
suite.assertStrictEqual('$or op test3', eic.chain().find({ | ||
'$or': [{ | ||
'testid': 1 | ||
}, { | ||
'testFloat': { | ||
'$gt': 7.0 | ||
} | ||
}] | ||
}).data().length, 5); | ||
// resultset.find $or | ||
suite.assertStrictEqual('$or op test2', eic.chain().find({ | ||
'$or': [ | ||
{'testid': 1}, | ||
{'testString': 'bbb'} | ||
] | ||
}).data().length, 3); | ||
// add index and repeat final test | ||
eic.ensureIndex("testid"); | ||
// resultset.find explicit operators | ||
suite.assertStrictEqual('$or op test3', eic.chain().find({ | ||
'$or': [ | ||
{'testid': 1}, | ||
{'testFloat': {'$gt': 7.0}} | ||
] | ||
}).data().length, 5); | ||
suite.assertStrictEqual('$and op test4', eic.chain().find({ | ||
'$and': [{ | ||
'testid': { | ||
'$eq': 1 | ||
} | ||
}, { | ||
'testFloat': { | ||
'$gt': 6.0 | ||
} | ||
}] | ||
}).data().length, 1); | ||
// add index and repeat final test | ||
eic.ensureIndex("testid"); | ||
suite.assertStrictEqual('$or op test4', eic.chain().find({ | ||
'$or': [{ | ||
'testid': 1 | ||
}, { | ||
'testFloat': { | ||
'$gt': 7.0 | ||
} | ||
}] | ||
}).data().length, 5); | ||
suite.assertStrictEqual('$and op test4', eic.chain().find({ | ||
'$and': [ | ||
{'testid': {'$eq': 1}}, | ||
{'testFloat': {'$gt': 6.0}} | ||
] | ||
}).data().length, 1); | ||
db.removeCollection("eic"); | ||
}) | ||
}) | ||
suite.assertStrictEqual('$or op test4', eic.chain().find({ | ||
'$or': [ | ||
{'testid': 1}, | ||
{'testFloat': {'$gt': 7.0}} | ||
] | ||
}).data().length, 5); | ||
describe('findOne', function () { | ||
it('works', function () { | ||
var eic = db.addCollection("eic"); | ||
db.removeCollection("eic"); | ||
} | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'hhh', | ||
'testFloat': 5.2 | ||
}); //0 | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'bbb', | ||
'testFloat': 6.2 | ||
}); //1 | ||
eic.insert({ | ||
'testid': 5, | ||
'testString': 'zzz', | ||
'testFloat': 7.2 | ||
}); //2 | ||
function testFindOne() { | ||
var eic = db.addCollection("eic"); | ||
// coll.findOne return type | ||
suite.assertStrictEqual('findOne return type', typeof eic.findOne({ | ||
'testid': 1 | ||
}), 'object'); | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'hhh', | ||
'testFloat': 5.2 | ||
}); //0 | ||
eic.insert({ | ||
'testid': 1, | ||
'testString': 'bbb', | ||
'testFloat': 6.2 | ||
}); //1 | ||
eic.insert({ | ||
'testid': 5, | ||
'testString': 'zzz', | ||
'testFloat': 7.2 | ||
}); //2 | ||
// coll.findOne return match | ||
suite.assertStrictEqual('findOne return match', eic.findOne({ | ||
'testid': 5 | ||
}).testFloat, 7.2); | ||
// coll.findOne return type | ||
suite.assertStrictEqual('findOne return type', typeof eic.findOne({'testid': 1}), 'object'); | ||
// findOne with $and op | ||
suite.assertStrictEqual('findOne with $and op', eic.findOne({ | ||
'$and': [{ | ||
'testid': 1 | ||
}, { | ||
'testString': 'bbb' | ||
}] | ||
}).testFloat, 6.2); | ||
// coll.findOne return match | ||
suite.assertStrictEqual('findOne return match', eic.findOne({'testid': 5}).testFloat, 7.2); | ||
// findOne with $and op | ||
suite.assertStrictEqual('findOne with $or op', eic.findOne({ | ||
'$or': [{ | ||
'testid': 2 | ||
}, { | ||
'testString': 'zzz' | ||
}] | ||
}).testFloat, 7.2); | ||
// findOne with $and op | ||
suite.assertStrictEqual('findOne with $and op', eic.findOne({ | ||
'$and': [ | ||
{'testid': 1}, | ||
{'testString': 'bbb'} | ||
] | ||
}).testFloat, 6.2); | ||
db.removeCollection("eic"); | ||
}) | ||
}) | ||
// findOne with $and op | ||
suite.assertStrictEqual('findOne with $or op', eic.findOne({ | ||
'$or': [ | ||
{'testid': 2}, | ||
{'testString': 'zzz'} | ||
] | ||
}).testFloat, 7.2); | ||
/* Dynamic View Tests */ | ||
describe('stepEvaluateDocument', function () { | ||
it('works', function () { | ||
var view = users.addDynamicView('test'); | ||
var query = { | ||
'age': { | ||
'$gt': 24 | ||
} | ||
}; | ||
db.removeCollection("eic"); | ||
} | ||
view.applyFind(query); | ||
/* Dynamic View Tests */ | ||
function stepEvaluateDocument() { | ||
var view = users.addDynamicView('test'); | ||
var query = { | ||
'age': { | ||
'$gt': 24 | ||
} | ||
}; | ||
// churn evaluateDocuments() to make sure it works right | ||
jonas.age = 23; | ||
users.update(jonas); | ||
view.applyFind(query); | ||
suite.assertStrictEqual("evalDoc1", view.data().length, users.data.length - 1); | ||
jonas.age = 30; | ||
users.update(jonas); | ||
suite.assertStrictEqual("evalDoc2", view.data().length, users.data.length); | ||
jonas.age = 23; | ||
users.update(jonas); | ||
suite.assertStrictEqual("evalDoc3", view.data().length, users.data.length - 1); | ||
jonas.age = 30; | ||
users.update(jonas); | ||
suite.assertStrictEqual("evalDoc4", view.data().length, users.data.length); | ||
// churn evaluateDocuments() to make sure it works right | ||
jonas.age = 23; | ||
users.update(jonas); | ||
// assert set equality of docArrays irrelevant of sort/sequence | ||
var result1 = users.find(query).sort(docCompare); | ||
var result2 = view.data().sort(docCompare); | ||
result1.forEach(function (obj) { | ||
delete obj.meta | ||
}); | ||
result2.forEach(function (obj) { | ||
delete obj.meta | ||
}); | ||
suite.assertStrictEqual("evalDoc1", view.data().length, users.data.length - 1); | ||
jonas.age = 30; | ||
users.update(jonas); | ||
suite.assertStrictEqual("evalDoc2", view.data().length, users.data.length); | ||
jonas.age = 23; | ||
users.update(jonas); | ||
suite.assertStrictEqual("evalDoc3", view.data().length, users.data.length - 1); | ||
jonas.age = 30; | ||
users.update(jonas); | ||
suite.assertStrictEqual("evalDoc4", view.data().length, users.data.length); | ||
suite.assertEqual('Result data Equality', result1, result2); | ||
// assert set equality of docArrays irrelevant of sort/sequence | ||
var result1 = users.find(query).sort(docCompare); | ||
var result2 = view.data().sort(docCompare); | ||
result1.forEach(function (obj) { | ||
delete obj.meta | ||
}); | ||
result2.forEach(function (obj) { | ||
delete obj.meta | ||
}); | ||
suite.assertNotStrictEqual('Strict Equality', users.find(query), view.data()); | ||
suite.assertEqual('View data equality', view.resultset, view.resultset.copy()); | ||
suite.assertNotStrictEqual('View data copy strict equality', view.resultset, view.resultset.copy()); | ||
suite.assertEqual('Result data Equality', result1, result2); | ||
return view; | ||
}) | ||
}) | ||
suite.assertNotStrictEqual('Strict Equality', users.find(query), view.data()); | ||
suite.assertEqual('View data equality', view.resultset, view.resultset.copy()); | ||
suite.assertNotStrictEqual('View data copy strict equality', view.resultset, view.resultset.copy()); | ||
describe('stepDynamicViewPersistence', function () { | ||
it('works', function stepDynamicViewPersistence() { | ||
var query = { | ||
'age': { | ||
'$gt': 24 | ||
} | ||
}; | ||
return view; | ||
} | ||
// set up a persistent dynamic view with sort | ||
var pview = users.addDynamicView('test2', true); | ||
pview.applyFind(query); | ||
pview.applySimpleSort("age"); | ||
// make sure view persistence works as expected | ||
function stepDynamicViewPersistence() { | ||
var query = { | ||
'age': { | ||
'$gt': 24 | ||
} | ||
}; | ||
// the dynamic view depends on an internal resultset | ||
// the persistent dynamic view also depends on an internal resultdata data array | ||
// filteredrows should be applied immediately to resultset will be lazily built into resultdata later when data() is called | ||
suite.assertStrictEqual("dynamic view initialization 1", pview.resultset.filteredrows.length, 3); | ||
suite.assertStrictEqual("dynamic view initialization 2", pview.resultdata.length, 0); | ||
// set up a persistent dynamic view with sort | ||
var pview = users.addDynamicView('test2', true); | ||
pview.applyFind(query); | ||
pview.applySimpleSort("age"); | ||
// compare how many documents are in results before adding new ones | ||
var pviewResultsetLenBefore = pview.resultset.filteredrows.length; | ||
// the dynamic view depends on an internal resultset | ||
// the persistent dynamic view also depends on an internal resultdata data array | ||
// filteredrows should be applied immediately to resultset will be lazily built into resultdata later when data() is called | ||
suite.assertStrictEqual("dynamic view initialization 1", pview.resultset.filteredrows.length, 3); | ||
suite.assertStrictEqual("dynamic view initialization 2", pview.resultdata.length, 0); | ||
users.insert({ | ||
name: 'abc', | ||
age: 21, | ||
lang: 'English' | ||
}); | ||
// compare how many documents are in results before adding new ones | ||
var pviewResultsetLenBefore = pview.resultset.filteredrows.length; | ||
users.insert({ | ||
name: 'def', | ||
age: 25, | ||
lang: 'English' | ||
}); | ||
users.insert({ | ||
name: 'abc', | ||
age: 21, | ||
lang: 'English' | ||
}); | ||
// now see how many are in resultset (without rebuilding persistent view) | ||
var pviewResultsetLenAfter = pview.resultset.filteredrows.length; | ||
users.insert({ | ||
name: 'def', | ||
age: 25, | ||
lang: 'English' | ||
}); | ||
// only one document should have been added to resultset (1 was filtered out) | ||
suite.assertStrictEqual("dv resultset is 'set' valid", pviewResultsetLenBefore + 1, pviewResultsetLenAfter); | ||
// now see how many are in resultset (without rebuilding persistent view) | ||
var pviewResultsetLenAfter = pview.resultset.filteredrows.length; | ||
// Test sorting and lazy build of resultdata | ||
// only one document should have been added to resultset (1 was filtered out) | ||
suite.assertStrictEqual("dv resultset is 'set' valid", pviewResultsetLenBefore + 1, pviewResultsetLenAfter); | ||
// retain copy of internal resultset's filteredrows before lazy sort | ||
var frcopy = pview.resultset.filteredrows.slice(); | ||
pview.data(); | ||
// now make a copy of internal result's filteredrows after lazy sort | ||
var frcopy2 = pview.resultset.filteredrows.slice(); | ||
// Test sorting and lazy build of resultdata | ||
// verify filteredrows logically matches resultdata (irrelevant of sort) | ||
for (var idxFR = 0; idxFR < frcopy2.length; idxFR++) { | ||
suite.assertEqual("dynamic view resultset/resultdata consistency", pview.resultdata[idxFR], pview.collection.data[frcopy2[idxFR]]); | ||
} | ||
// now verify they are not exactly equal (verify sort moved stuff) | ||
suite.assertNotEqual('dynamic view sort', frcopy, frcopy2); | ||
}) | ||
}) | ||
// retain copy of internal resultset's filteredrows before lazy sort | ||
var frcopy = pview.resultset.filteredrows.slice(); | ||
pview.data(); | ||
// now make a copy of internal result's filteredrows after lazy sort | ||
var frcopy2 = pview.resultset.filteredrows.slice(); | ||
describe('stepDynamicViewPersistence', function () { | ||
it('works', function duplicateItemFoundOnIndex() { | ||
var test = db.addCollection('nodupes', ['index']); | ||
// verify filteredrows logically matches resultdata (irrelevant of sort) | ||
for (var idxFR = 0; idxFR < frcopy2.length; idxFR++) { | ||
suite.assertEqual("dynamic view resultset/resultdata consistency", pview.resultdata[idxFR], pview.collection.data[frcopy2[idxFR]]); | ||
} | ||
// now verify they are not exactly equal (verify sort moved stuff) | ||
suite.assertNotEqual('dynamic view sort', frcopy, frcopy2); | ||
} | ||
var item = test.insert({ | ||
index: 'key', | ||
a: 1 | ||
}); | ||
function testDynamicView() { | ||
var view = stepEvaluateDocument(); | ||
stepDynamicViewPersistence(); | ||
} | ||
var results = test.find({ | ||
index: 'key' | ||
}); | ||
suite.assertStrictEqual('one result exists', results.length, 1); | ||
suite.assertStrictEqual('the correct result is returned', results[0].a, 1); | ||
function duplicateItemFoundOnIndex() { | ||
var test = db.addCollection('nodupes', ['index']); | ||
item.a = 2; | ||
test.update(item); | ||
var item = test.insert({ | ||
index: 'key', | ||
a: 1 | ||
}); | ||
results = test.find({ | ||
index: 'key' | ||
}); | ||
suite.assertStrictEqual('one result exists', results.length, 1); | ||
suite.assertStrictEqual('the correct result is returned', results[0].a, 2); | ||
}) | ||
}) | ||
var results = test.find({ | ||
index: 'key' | ||
}); | ||
suite.assertStrictEqual('one result exists', results.length, 1); | ||
suite.assertStrictEqual('the correct result is returned', results[0].a, 1); | ||
describe('stepDynamicViewPersistence', function () { | ||
it('works', function testEmptyTableWithIndex() { | ||
var itc = db.addCollection('test', ['testindex']); | ||
item.a = 2; | ||
test.update(item); | ||
var resultsNoIndex = itc.find({ | ||
'testid': 2 | ||
}); | ||
suite.assertStrictEqual('no results found', resultsNoIndex.length, 0); | ||
results = test.find({ | ||
index: 'key' | ||
}); | ||
suite.assertStrictEqual('one result exists', results.length, 1); | ||
suite.assertStrictEqual('the correct result is returned', results[0].a, 2); | ||
} | ||
var resultsWithIndex = itc.find({ | ||
'testindex': 4 | ||
}); | ||
suite.assertStrictEqual('no results found', resultsWithIndex.length, 0); | ||
}) | ||
}) | ||
function testEmptyTableWithIndex() { | ||
var itc = db.addCollection('test', ['testindex']); | ||
describe('stepDynamicViewPersistence', function () { | ||
it('works', function testAnonym() { | ||
var coll = db.anonym([{ | ||
name: 'joe' | ||
}, { | ||
name: 'jack' | ||
}], ['name']); | ||
suite.assertEqual('Anonym collection', coll.data.length, 2); | ||
suite.assertEqual('Collection not found', db.getCollection('anonym'), null); | ||
coll.name = 'anonym'; | ||
db.loadCollection(coll); | ||
suite.assertEqual('Anonym collection loaded', !!db.getCollection('anonym'), true); | ||
coll.clear(); | ||
suite.assertEqual('No data after coll.clear()', 0, coll.data.length); | ||
}) | ||
}) | ||
var resultsNoIndex = itc.find({ | ||
'testid': 2 | ||
}); | ||
suite.assertStrictEqual('no results found', resultsNoIndex.length, 0); | ||
describe('stepDynamicViewPersistence', function () { | ||
it('works', function testCollections() { | ||
var db = new loki('testCollections'); | ||
db.name = 'testCollections'; | ||
suite.assertEqual('DB name', db.getName(), 'testCollections'); | ||
var t = db.addCollection('test1', { | ||
transactional: true | ||
}); | ||
db.addCollection('test2'); | ||
suite.assertThrows('Throw error on wrong remove', function () { | ||
t.remove('foo'); | ||
}, Error); | ||
suite.assertThrows('Throw error on non-synced doc', function () { | ||
t.remove({ | ||
name: 'joe' | ||
}); | ||
}, Error); | ||
suite.assertEqual('List collections', db.listCollections().length, 2); | ||
t.clear(); | ||
var users = [{ | ||
name: 'joe' | ||
}, { | ||
name: 'dave' | ||
}]; | ||
t.insert(users); | ||
var resultsWithIndex = itc.find({ | ||
'testindex': 4 | ||
}); | ||
suite.assertStrictEqual('no results found', resultsWithIndex.length, 0); | ||
} | ||
suite.assertEqual('2 docs after array insert', 2, t.data.length); | ||
t.remove(users); | ||
suite.assertEqual('0 docs after array remove', 0, t.data.length); | ||
function testAnonym() { | ||
var coll = db.anonym([{ | ||
name: 'joe' | ||
}, { | ||
name: 'jack' | ||
}], ['name']); | ||
suite.assertEqual('Anonym collection', coll.data.length, 2); | ||
suite.assertEqual('Collection not found', db.getCollection('anonym'), null); | ||
coll.name = 'anonym'; | ||
db.loadCollection(coll); | ||
suite.assertEqual('Anonym collection loaded', !!db.getCollection('anonym'), true); | ||
coll.clear(); | ||
suite.assertEqual('No data after coll.clear()', 0, coll.data.length); | ||
} | ||
function TestError() {} | ||
TestError.prototype = new Error; | ||
db.autosaveEnable(); | ||
db.on('close', function () { | ||
throw new TestError; | ||
}); | ||
suite.assertThrows('Throw error on purpose on close', function () { | ||
db.close(function () { | ||
return; | ||
}); | ||
}, TestError); | ||
}) | ||
}) | ||
function testCollections() { | ||
var db = new loki('testCollections'); | ||
db.name = 'testCollections'; | ||
suite.assertEqual('DB name', db.getName(), 'testCollections'); | ||
var t = db.addCollection('test1', { | ||
transactional: true | ||
}); | ||
db.addCollection('test2'); | ||
suite.assertThrows('Throw error on wrong remove', function () { | ||
t.remove('foo'); | ||
}, Error); | ||
suite.assertThrows('Throw error on non-synced doc', function () { | ||
t.remove({ | ||
name: 'joe' | ||
}); | ||
}, Error); | ||
suite.assertEqual('List collections', db.listCollections().length, 2); | ||
t.clear(); | ||
var users = [{ | ||
name: 'joe' | ||
}, { | ||
name: 'dave' | ||
}]; | ||
t.insert(users); | ||
suite.assertEqual('2 docs after array insert', 2, t.data.length); | ||
t.remove(users); | ||
suite.assertEqual('0 docs after array remove', 0, t.data.length); | ||
function TestError() {} | ||
TestError.prototype = new Error; | ||
db.autosaveEnable(); | ||
db.on('close', function () { | ||
throw new TestError; | ||
}); | ||
suite.assertThrows('Throw error on purpose on close', function () { | ||
db.close(function () { | ||
return; | ||
}); | ||
}, TestError); | ||
} | ||
/* Main Test */ | ||
populateTestData(); | ||
testCoreMethods(); | ||
testAndOrOps(); | ||
testFindOne(); | ||
testCalculateRange(); | ||
testIndexes(); | ||
testIndexLifecycle(); | ||
testResultset(); | ||
testDynamicView(); | ||
duplicateItemFoundOnIndex(); | ||
testEmptyTableWithIndex(); | ||
testAnonym(); | ||
testCollections(); | ||
suite.report(); | ||
}) | ||
/* Main Test */ | ||
// populateTestData(); | ||
// testCoreMethods(); | ||
// testAndOrOps(); | ||
// testFindOne(); | ||
// testCalculateRange(); | ||
// testIndexes(); | ||
// testIndexLifecycle(); | ||
// testResultset(); | ||
// testDynamicView(); | ||
// duplicateItemFoundOnIndex(); | ||
// testEmptyTableWithIndex(); | ||
// testAnonym(); | ||
// testCollections(); | ||
// suite.report(); |
@@ -1,20 +0,19 @@ | ||
var Loki = require('../src/lokijs.js'), | ||
gordian = require('gordian'), | ||
suite = new gordian('testCollection'); | ||
describe('collection', function () { | ||
it('works', function () { | ||
function SubclassedCollection() { | ||
loki.Collection.apply(this, Array.prototype.slice.call(arguments)); | ||
} | ||
SubclassedCollection.prototype = new loki.Collection; | ||
SubclassedCollection.prototype.extendedMethod = function () { | ||
return this.name.toUpperCase(); | ||
} | ||
var coll = new SubclassedCollection('users', {}); | ||
function SubclassedCollection() { | ||
Loki.Collection.apply(this, Array.prototype.slice.call(arguments)); | ||
} | ||
SubclassedCollection.prototype = new Loki.Collection; | ||
SubclassedCollection.prototype.extendedMethod = function () { | ||
return this.name.toUpperCase(); | ||
} | ||
var coll = new SubclassedCollection('users', {}); | ||
suite.assertEqual('Exposed Collection is not null', true, coll != null); | ||
suite.assertEqual('Exposed Collection methods work normally', 'users'.toUpperCase(), coll.extendedMethod()); | ||
coll.insert({ | ||
name: 'joe' | ||
expect(coll != null).toBe(true); | ||
expect('users'.toUpperCase()).toEqual(coll.extendedMethod()); | ||
coll.insert({ | ||
name: 'joe' | ||
}); | ||
expect(coll.data.length).toEqual(1); | ||
}); | ||
}); | ||
suite.assertEqual('Exposed Collection operations work normally', coll.data.length, 1); | ||
suite.report(); |
var fs = require("fs"); | ||
var isError = require('util').isError; | ||
// var fs = require("fs"); | ||
// var isError = require('util').isError; | ||
// these 2 function test the interworking between Lokijs and the adapter | ||
function saveTest(){ | ||
users.insert([{ | ||
name: 'joe' | ||
}, { | ||
name: 'jack' | ||
}]); | ||
db.saveDatabase(reloadTest); | ||
} | ||
// // these 2 function test the interworking between Lokijs and the adapter | ||
// function saveTest(){ | ||
// users.insert([{ | ||
// name: 'joe' | ||
// }, { | ||
// name: 'jack' | ||
// }]); | ||
// db.saveDatabase(reloadTest); | ||
// } | ||
function reloadTest(){ | ||
var reloaded = new loki('./loki.json.crypted',{ adapter: cryptedFileAdapter }); | ||
reloaded.loadDatabase({}, function () { | ||
var users2 = reloaded.getCollection('users'); | ||
suite.assertEqual('There are 2 objects in the reloaded and decrypted db', 2, users2.data.length); | ||
errorHandlingTest(); | ||
}); | ||
} | ||
// function reloadTest(){ | ||
// var reloaded = new loki('./loki.json.crypted',{ adapter: cryptedFileAdapter }); | ||
// reloaded.loadDatabase({}, function () { | ||
// var users2 = reloaded.getCollection('users'); | ||
// suite.assertEqual('There are 2 objects in the reloaded and decrypted db', 2, users2.data.length); | ||
// errorHandlingTest(); | ||
// }); | ||
// } | ||
function errorHandlingTest(){ | ||
var reloaded = new loki('./nonExistingDatabase',{ adapter: cryptedFileAdapter }); | ||
reloaded.loadDatabase({}, function (r){ | ||
suite.assertStrictEqual('Missing database caught by loadDatabase and passed via Lokijs', (r !== undefined) , true); | ||
noSecretOnSaveTest(); | ||
}); | ||
} | ||
// function errorHandlingTest(){ | ||
// var reloaded = new loki('./nonExistingDatabase',{ adapter: cryptedFileAdapter }); | ||
// reloaded.loadDatabase({}, function (r){ | ||
// suite.assertStrictEqual('Missing database caught by loadDatabase and passed via Lokijs', (r !== undefined) , true); | ||
// noSecretOnSaveTest(); | ||
// }); | ||
// } | ||
// now on to testing error handling in the adapter itself | ||
// // now on to testing error handling in the adapter itself | ||
function noSecretOnSaveTest(){ | ||
// function noSecretOnSaveTest(){ | ||
cryptedFileAdapter.setSecret(undefined); | ||
cryptedFileAdapter.saveDatabase('./testfile.json',"{}", | ||
function(r){ | ||
suite.assertStrictEqual('Missing secret caught on saveDatabase', isError(r), true); | ||
noSecretOnLoadTest(); | ||
}); | ||
} | ||
// cryptedFileAdapter.setSecret(undefined); | ||
function noSecretOnLoadTest(){ | ||
cryptedFileAdapter.loadDatabase('./loki.json.crypted', | ||
function(r){ | ||
suite.assertStrictEqual('Missing secret caught by loadDatabase', isError(r), true); | ||
missingDbTest(); | ||
}); | ||
} | ||
// cryptedFileAdapter.saveDatabase('./testfile.json',"{}", | ||
// function(r){ | ||
// suite.assertStrictEqual('Missing secret caught on saveDatabase', isError(r), true); | ||
// noSecretOnLoadTest(); | ||
// }); | ||
// } | ||
function missingDbTest(){ | ||
cryptedFileAdapter.setSecret('mySecret'); | ||
cryptedFileAdapter.loadDatabase("./nonExistingDatabase", | ||
function(r){ | ||
suite.assertStrictEqual('Missing database caught by loadDatabase', isError(r), true); | ||
noJsonTest(); | ||
}); | ||
} | ||
// function noSecretOnLoadTest(){ | ||
// cryptedFileAdapter.loadDatabase('./loki.json.crypted', | ||
// function(r){ | ||
// suite.assertStrictEqual('Missing secret caught by loadDatabase', isError(r), true); | ||
// missingDbTest(); | ||
// }); | ||
// } | ||
function noJsonTest(){ | ||
fs.writeFileSync("./nonJsonTestFile.txt","this is not json",'utf8'); | ||
cryptedFileAdapter.loadDatabase("./nonJsonTestFile.txt", | ||
function(r){ | ||
fs.unlink("./nonJsonTestFile.txt"); | ||
suite.assertStrictEqual('No Json content caught by loadDatabase', isError(r), true); | ||
wrongJsonTest(); | ||
}); | ||
} | ||
// function missingDbTest(){ | ||
// cryptedFileAdapter.setSecret('mySecret'); | ||
function wrongJsonTest(){ | ||
fs.writeFileSync("./wrongJsonTestFile.txt",'{"name":"value"}','utf8'); | ||
cryptedFileAdapter.loadDatabase("./wrongJsonTestFile.txt", | ||
function(r){ | ||
fs.unlink("./wrongJsonTestFile.txt"); | ||
suite.assertStrictEqual('Wrong Json content caught by loadDatabase', isError(r), true); | ||
endOfTest(); | ||
}); | ||
} | ||
// cryptedFileAdapter.loadDatabase("./nonExistingDatabase", | ||
// function(r){ | ||
// suite.assertStrictEqual('Missing database caught by loadDatabase', isError(r), true); | ||
// noJsonTest(); | ||
// }); | ||
// } | ||
function endOfTest(){ | ||
suite.report(); | ||
fs.unlink('./loki.json.crypted'); | ||
} | ||
// function noJsonTest(){ | ||
// fs.writeFileSync("./nonJsonTestFile.txt","this is not json",'utf8'); | ||
// cryptedFileAdapter.loadDatabase("./nonJsonTestFile.txt", | ||
// function(r){ | ||
// fs.unlink("./nonJsonTestFile.txt"); | ||
// suite.assertStrictEqual('No Json content caught by loadDatabase', isError(r), true); | ||
// wrongJsonTest(); | ||
// }); | ||
// } | ||
var cryptedFileAdapter = require('../src/lokiCryptedFileAdapter'); | ||
// function wrongJsonTest(){ | ||
// fs.writeFileSync("./wrongJsonTestFile.txt",'{"name":"value"}','utf8'); | ||
// cryptedFileAdapter.loadDatabase("./wrongJsonTestFile.txt", | ||
// function(r){ | ||
// fs.unlink("./wrongJsonTestFile.txt"); | ||
// suite.assertStrictEqual('Wrong Json content caught by loadDatabase', isError(r), true); | ||
// endOfTest(); | ||
// }); | ||
// } | ||
cryptedFileAdapter.setSecret('mySecret'); | ||
var loki = require('../src/lokijs.js'), | ||
db = new loki('./loki.json.crypted',{ adapter: cryptedFileAdapter }), | ||
gordian = require('gordian'), | ||
suite = new gordian('testCryptedFileAdapter'), | ||
users = db.addCollection('users'); | ||
// function endOfTest(){ | ||
// suite.report(); | ||
// fs.unlink('./loki.json.crypted'); | ||
// } | ||
saveTest(); | ||
// var cryptedFileAdapter = require('../src/lokiCryptedFileAdapter'); | ||
// cryptedFileAdapter.setSecret('mySecret'); | ||
// var loki = require('../src/lokijs.js'), | ||
// db = new loki('./loki.json.crypted',{ adapter: cryptedFileAdapter }), | ||
// gordian = require('gordian'), | ||
// suite = new gordian('testCryptedFileAdapter'), | ||
// users = db.addCollection('users'); | ||
// saveTest(); | ||
@@ -110,1 +107,4 @@ | ||
@@ -1,21 +0,23 @@ | ||
var loki = require('../src/lokijs.js'), | ||
gordian = require('gordian'), | ||
suite = new gordian('testKv'), | ||
store = new loki.KeyValueStore(); | ||
// var loki = require('../src/lokijs.js'), | ||
// gordian = require('gordian'), | ||
// suite = new gordian('testKv'), | ||
// store = new loki.KeyValueStore(); | ||
var key = { | ||
name: 'joe' | ||
}, | ||
value = { | ||
position: 'developer' | ||
}; | ||
describe('kv', function () { | ||
it('works', function () { | ||
var store = new loki.KeyValueStore(); | ||
var key = { | ||
name: 'joe' | ||
}, | ||
value = { | ||
position: 'developer' | ||
}; | ||
store.set('foo', 'bar'); | ||
store.set('bar', 'baz'); | ||
store.set('baz', 'quux'); | ||
store.set(key, value); | ||
//store.set(key, value); | ||
console.log(store.keys, store.values) | ||
suite.assertEqual('Finding key and value', 'bar', store.get('foo')); | ||
suite.assertEqual('Finding key by object', value, store.get(key)); | ||
suite.report(); | ||
store.set('foo', 'bar'); | ||
store.set('bar', 'baz'); | ||
store.set('baz', 'quux'); | ||
store.set(key, value); | ||
expect('bar').toEqual(store.get('foo')); | ||
expect(value).toEqual(store.get(key)); | ||
}); | ||
}); |
@@ -1,52 +0,58 @@ | ||
var loki = require('../src/lokijs.js'), | ||
db = new loki(), | ||
gordian = require('gordian'), | ||
suite = new gordian('testEvents'), | ||
users = db.addCollection('users'); | ||
// var loki = require('../src/lokijs.js'), | ||
// db = new loki(), | ||
// gordian = require('gordian'), | ||
// suite = new gordian('testEvents'), | ||
// users = db.addCollection('users'); | ||
users.insert({ | ||
name: 'joe', | ||
age: 39 | ||
}); | ||
users.insert({ | ||
name: 'jack', | ||
age: 20 | ||
}); | ||
users.insert({ | ||
name: 'jim', | ||
age: 40 | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 33 | ||
}); | ||
users.insert({ | ||
name: 'jim', | ||
age: 29 | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 21 | ||
}); | ||
describe('remove', function () { | ||
it('removes', function () { | ||
var db = new loki(); | ||
var users = db.addCollection('users'); | ||
var dv = users.addDynamicView('testview'); | ||
dv.applyWhere(function (obj) { | ||
return obj.name.length > 3; | ||
}); | ||
users.insert({ | ||
name: 'joe', | ||
age: 39 | ||
}); | ||
users.insert({ | ||
name: 'jack', | ||
age: 20 | ||
}); | ||
users.insert({ | ||
name: 'jim', | ||
age: 40 | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 33 | ||
}); | ||
users.insert({ | ||
name: 'jim', | ||
age: 29 | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 21 | ||
}); | ||
users.removeWhere(function (obj) { | ||
return obj.age > 35; | ||
var dv = users.addDynamicView('testview'); | ||
dv.applyWhere(function (obj) { | ||
return obj.name.length > 3; | ||
}); | ||
users.removeWhere(function (obj) { | ||
return obj.age > 35; | ||
}); | ||
expect(users.data.length).toEqual(4); | ||
users.removeWhere({ | ||
'age': { | ||
$gt: 25 | ||
} | ||
}); | ||
expect(users.data.length).toEqual(2); | ||
users.remove(6); | ||
expect(users.data.length).toEqual(1); | ||
users.removeDataOnly(); | ||
expect(users.data.length).toEqual(0); | ||
expect(!!users.getDynamicView('testview')).toEqual(true); | ||
}); | ||
}); | ||
suite.assertEqual('Users length after removeWhere()', users.data.length, 4); | ||
users.removeWhere({ | ||
'age': { | ||
$gt: 25 | ||
} | ||
}); | ||
suite.assertEqual('Users length after removeWhere()', users.data.length, 2); | ||
users.remove(6); | ||
suite.assertEqual('Users length after remove(int)', users.data.length, 1); | ||
users.removeDataOnly(); | ||
suite.assertEqual('No users left after removeDataOnly()', users.data.length, 0); | ||
suite.assertEqual('DynamicView still in existence after removing data', !!users.getDynamicView('testview'), true); | ||
suite.report(); |
@@ -1,66 +0,96 @@ | ||
var loki = require('../src/lokijs.js'), | ||
db = new loki(), | ||
gordian = require('gordian'), | ||
suite = new gordian('testEvents'), | ||
users = db.addCollection('users'); | ||
// var loki = require('../src/lokijs.js'), | ||
// db = new loki(), | ||
// gordian = require('gordian'), | ||
// suite = new gordian('testEvents'), | ||
// users = db.addCollection('users'); | ||
users.insert({ | ||
name: 'joe', | ||
age: 35, | ||
relatives: { | ||
firstgrade: 15 | ||
} | ||
describe('stats', function () { | ||
var db = new loki(); | ||
var users = db.addCollection('users'); | ||
users.insert({ | ||
name: 'joe', | ||
age: 35, | ||
relatives: { | ||
firstgrade: 15 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'jack', | ||
age: 20, | ||
relatives: { | ||
firstgrade: 20 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'jim', | ||
age: 40, | ||
relatives: { | ||
firstgrade: 32 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 15, | ||
relatives: { | ||
firstgrade: 20 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'jim', | ||
age: 28, | ||
relatives: { | ||
firstgrade: 15 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 12, | ||
relatives: { | ||
firstgrade: 12 | ||
} | ||
}); | ||
it('max should be 32', function () { | ||
expect(users.max('relatives.firstgrade')).toEqual(32); | ||
}); | ||
it('max record should be 3, 32', function () { | ||
suite.assertEqual('Max record: ', { | ||
index: 3, | ||
value: 32 | ||
}, users.maxRecord('relatives.firstgrade')); | ||
}); | ||
it('min should be 12', function () { | ||
expect(users.min('age')).toEqual(12); | ||
}); | ||
it('min record to be 6, 12', function () { | ||
expect(users.minRecord('age')).toEqual({ | ||
index: 6, | ||
value: 12 | ||
}); | ||
}); | ||
it('average to be 19', function () { | ||
expect(users.avg('relatives.firstgrade')).toEqual(19); | ||
}); | ||
it('median to be 17.5', function () { | ||
expect(users.median('relatives.firstgrade')).toEqual(17.5); | ||
}); | ||
it('ages should be [35, 20, 40, 15, 28, 12]', function () { | ||
expect(users.extract('age')).toEqual([35, 20, 40, 15, 28, 12]); | ||
}); | ||
it('Standard deviation on firstgrade relatives should be 6.48...', function () { | ||
expect(users.stdDev('relatives.firstgrade')).toEqual(6.48074069840786); | ||
}); | ||
it('stdDev should be 10.23...', function () { | ||
expect(users.stdDev('age')).toEqual(10.23067283548187); | ||
}); | ||
}); | ||
users.insert({ | ||
name: 'jack', | ||
age: 20, | ||
relatives: { | ||
firstgrade: 20 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'jim', | ||
age: 40, | ||
relatives: { | ||
firstgrade: 32 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 15, | ||
relatives: { | ||
firstgrade: 20 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'jim', | ||
age: 28, | ||
relatives: { | ||
firstgrade: 15 | ||
} | ||
}); | ||
users.insert({ | ||
name: 'dave', | ||
age: 12, | ||
relatives: { | ||
firstgrade: 12 | ||
} | ||
}); | ||
suite.assertEqual('Simple max: ', 32, users.max('relatives.firstgrade')); | ||
suite.assertEqual('Max record: ', { | ||
index: 3, | ||
value: 32 | ||
}, users.maxRecord('relatives.firstgrade')); | ||
suite.assertEqual('Simple min: ', 12, users.min('age')); | ||
suite.assertEqual('Min record: ', { | ||
index: 6, | ||
value: 12 | ||
}, users.minRecord('age')); | ||
suite.assertEqual('Average: ', 19, users.avg('relatives.firstgrade')); | ||
suite.assertEqual('Mode: ', 20, users.mode('relatives.firstgrade')); | ||
suite.assertEqual('Median: ', 17.5, users.median('relatives.firstgrade')); | ||
suite.assertEqual('Extract ages: ', [35, 20, 40, 15, 28, 12], users.extract('age')); | ||
suite.assertEqual('Standard deviation on firstgrade relatives: ', 6.48074069840786, users.stdDev('relatives.firstgrade')); | ||
suite.assertEqual('Standard deviation on ages: ', 10.23067283548187, users.stdDev('age')); | ||
suite.report(); |
@@ -1,72 +0,77 @@ | ||
var loki = require('../src/lokijs.js'), | ||
db, | ||
users, | ||
gordian = require('gordian'), | ||
suite = new gordian('testTyped'); | ||
// var loki = require('../src/lokijs.js'), | ||
// db, | ||
// users, | ||
// gordian = require('gordian'), | ||
// suite = new gordian('testTyped'); | ||
db = new loki('test.json'); | ||
describe('typed', function () { | ||
it('works', function () { | ||
var db = new loki('test.json'); | ||
var users; | ||
function User(n) { | ||
this.name = n || ''; | ||
this.log = function () { | ||
console.log('Name: ' + this.name); | ||
}; | ||
} | ||
function User(n) { | ||
this.name = n || ''; | ||
this.log = function () { | ||
console.log('Name: ' + this.name); | ||
}; | ||
} | ||
var json = { | ||
"filename": "test.json", | ||
"collections": [{ | ||
"name": "users", | ||
"data": [{ | ||
"name": "joe", | ||
"objType": "users", | ||
"meta": { | ||
"version": 0, | ||
"created": 1415467401386, | ||
"revision": 0 | ||
var json = { | ||
"filename": "test.json", | ||
"collections": [{ | ||
"name": "users", | ||
"data": [{ | ||
"name": "joe", | ||
"objType": "users", | ||
"meta": { | ||
"version": 0, | ||
"created": 1415467401386, | ||
"revision": 0 | ||
}, | ||
"$loki": 1 | ||
}, { | ||
"name": "jack", | ||
"objType": "users", | ||
"meta": { | ||
"version": 0, | ||
"created": 1415467401388, | ||
"revision": 0 | ||
}, | ||
"$loki": 2 | ||
}], | ||
"idIndex": [1, 2], | ||
"binaryIndices": {}, | ||
"objType": "users", | ||
"transactional": false, | ||
"cachedIndex": null, | ||
"cachedBinaryIndex": null, | ||
"cachedData": null, | ||
"maxId": 2, | ||
"DynamicViews": [], | ||
"events": { | ||
"insert": [null], | ||
"update": [null], | ||
"close": [], | ||
"flushbuffer": [], | ||
"error": [], | ||
"delete": [] | ||
} | ||
}], | ||
"events": { | ||
"close": [] | ||
}, | ||
"$loki": 1 | ||
}, { | ||
"name": "jack", | ||
"objType": "users", | ||
"meta": { | ||
"version": 0, | ||
"created": 1415467401388, | ||
"revision": 0 | ||
}, | ||
"$loki": 2 | ||
}], | ||
"idIndex": [1, 2], | ||
"binaryIndices": {}, | ||
"objType": "users", | ||
"transactional": false, | ||
"cachedIndex": null, | ||
"cachedBinaryIndex": null, | ||
"cachedData": null, | ||
"maxId": 2, | ||
"DynamicViews": [], | ||
"events": { | ||
"insert": [null], | ||
"update": [null], | ||
"close": [], | ||
"flushbuffer": [], | ||
"error": [], | ||
"delete": [] | ||
} | ||
}], | ||
"events": { | ||
"close": [] | ||
}, | ||
"ENV": "NODEJS", | ||
"fs": {} | ||
}; | ||
"ENV": "NODEJS", | ||
"fs": {} | ||
}; | ||
db.loadJSON(JSON.stringify(json), { | ||
users: { | ||
proto: User | ||
} | ||
db.loadJSON(JSON.stringify(json), { | ||
users: { | ||
proto: User | ||
} | ||
}); | ||
users = db.getCollection('users'); | ||
//suite.assertEqual('Inflated object prototype', users.get(1) instanceof User, true); | ||
expect(users.get(1) instanceof User).toBe(true); | ||
}); | ||
}); | ||
users = db.getCollection('users'); | ||
suite.assertEqual('Inflated object prototype', users.get(1) instanceof User, true); | ||
suite.report(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1230955
50
98
6
13
12102