Node.js/NW.js的持久化数据库:LinvoDB
特性:
- 类似MongoDB的查询引擎
- 构建在LevelUP之上的持久化,你可以选择不同的后端
- NW.js 友好- JS唯一后端是 Medea
- 性能 - 稳定的性能不受数据库大小 - 查询总是索引
- 自动索引
- 实时查询 - 使查询,得到持续最新的结果
- Schemas - built-in schema support
- Efficient Map / Reduce / Limit
与NeDB的关系
LinvoDB 是构建在 NeDB 之上,最显著核心的变化是,它使用的LevelUp作为后端。 meaning it doesn't have to keep the whole dataset in memory. LinvoDB also can do a query entirely by indexes, meaning it doesn't have to scan the full database on a query.
In general:
- LinvoDB is better for large datasets (many objects, or large objects) because it doesn't keep the whole DB in memory and doesn't need to always scan it
- LinvoDB does the entire query through the indexes, NeDB scans the DB
- Both LinvoDB and NeDB play well with NW.js (node-webkit). LinvoDB can be initialized with the JS-only MedeaDown back-end.
- NeDB is ultra-fast because the DB is in memory, LinvoDB's performance is comparible to MongoDB
- LinvoDB has live queries, map/reduce and schema support.
Install, Initialize, pick backend
Install:
npm install linvodb3 medeadown # For NW.js, using Medea npm install leveldb3 leveldown # For pure node.js, using LevelDB
Initialize:
var LinvoDB = require("linvodb3"); LinvoDB.defaults.store = { db: require("medeadown") }; // Comment out to use LevelDB instead of Medea var Doc = new LinvoDB("doc", { /* schema, can be empty */ })
Initialization, detailed:
var LinvoDB = require("linvodb3"); var modelName = "doc"; var schema = { }; // Non-strict always, can be left empty var options = { }; // options.filename = "./test.db"; // Path to database - not necessary // options.store = { db: require("medeadown") }; // Options passed to LevelUP constructor var Doc = new LinvoDB(modelName, schema, options); // New model; Doc is the constructor LinvoDB.dbPath // default path where data files are stored for each model LinvoDB.defaults // default options for every model
插入、保存
The native types areString,Number,Boolean,Dateandnull. You can also use arrays and subdocuments (objects). If a field isundefined, it will not be saved.
If the document does not contain an_idfield, one will be automatically generated (a 16-characters alphanumerical string). The_idof a document, once set, cannot be modified.
// Construct a single document and then save it var doc = new Doc({ a: 5, now: new Date(), test: "this is a string" }); doc.b = 13; // you can modify the doc doc.save(function(err) { // Document is saved console.log(doc._id); }); // Insert document(s) // you can use the .insert method to insert one or more documents Doc.insert({ a: 3 }, function (err, newDoc) { console.log(newDoc._id); }); Doc.insert([{ a: 3 }, { a: 42 }], function (err, newDocs) { // Two documents were inserted in the database // newDocs is an array with these documents, augmented with their _id // If there's an unique constraint on 'a', this will fail, and no changes will be made to the DB // err is a 'uniqueViolated' error }); // Save document(s) // save is like an insert, except it allows saving existing document too Doc.save([ doc, { a: 55, test: ".save is handy" } ], function(err, docs) { // docs[0] is doc // docs[1] is newly-inserted document with a=55 and has an assigned _id // Doing that with .insert would throw an uniqueViolated error for _id on doc, because it assumes all documents are new });
查询
Usefindto look for multiple documents matching you query, orfindOneto look for one specific document. You can select documents based on field equality or use comparison operators ($lt,$lte,$gt,$gte,$in,$nin,$ne,$regex,$exists). You can also use logical operators$or,$andand$not. See below for the syntax.
var Planet = new LinvoDB("planet", { /* schema, can be empty */ }) // Let's say our datastore contains the following collection Planet.save([ { _id: 'id1', planet: 'Mars', system: 'solar', inhabited: false, satellites: ['Phobos', 'Deimos'] }, { _id: 'id2', planet: 'Earth', system: 'solar', inhabited: true, humans: { genders: 2, eyes: true } }, { _id: 'id3', planet: 'Jupiter', system: 'solar', inhabited: false }, { _id: 'id4', planet: 'Omicron Persei 8', system: 'futurama', inhabited: true, humans: { genders: 7 } }, { _id: 'id5', completeData: { planets: [ { name: 'Earth', number: 3 }, { name: 'Mars', number: 2 }, { name: 'Pluton', number: 9 } ] } } ], function() { // Finding all planets in the solar system Planet.find({ system: 'solar' }, function (err, docs) { // docs is an array containing documents Mars, Earth, Jupiter // If no document is found, docs is equal to [] }); // Finding all inhabited planets in the solar system Planet.find({ system: 'solar', inhabited: true }, function (err, docs) { // docs is an array containing document Earth only }); // Use the dot-notation to match fields in subdocuments Planet.find({ "humans.genders": 2 }, function (err, docs) { // docs contains Earth }); // Use the dot-notation to navigate arrays of subdocuments Planet.find({ "completeData.planets.name": "Mars" }, function (err, docs) { // docs contains document 5 }); Planet.find({ "completeData.planets.0.name": "Earth" }, function (err, docs) { // docs contains document 5 // If we had tested against "Mars" docs would be empty because we are matching against a specific array element }); // You can also deep-compare objects. Don't confuse this with dot-notation! Planet.find({ humans: { genders: 2 } }, function (err, docs) { // docs is empty, because { genders: 2 } is not equal to { genders: 2, eyes: true } }); // Find all documents in the collection Planet.find({}, function (err, docs) { }); // The same rules apply when you want to only find one document Planet.findOne({ _id: 'id1' }, function (err, doc) { // doc is the document Mars // If no document is found, doc is null }); }); // end of .save()
项目主页:http://www.open-open.com/lib/view/home/1425800554753