GithubHelp home page GithubHelp logo

nstore's Introduction

nStore

A simple in-process key/value document store for node.js. nStore uses a safe append-only data format for quick inserts, updates, and deletes. Also a index of all documents and their exact location on the disk is stored in in memory for fast reads of any document. This append-only file format means that you can do online backups of the datastore using simple tools like rsync. The file is always in a consistent state.

Warning

This library is still under development. There are bugs. APIs will change. Docs may be wrong.

Keep in mind this is something I make in my free time and that's something I've had very little of lately thanks to my many other projects. I would love for someone with database and javascript smarts to partner with to make nStore super awesome.

Setup

All the examples assume this basic setup. Loading the database is async so there is a callback for when it's safe to query the database.

Creating a database is easy, you just call the nStore function to generate a collection object.

// Load the library
var nStore = require('nstore');
// Create a store
var users = nStore.new('data/users.db', function () {
  // It's loaded now
});

Creating a document

To insert/update documents, just call the save function on the collection.

// Insert a new document with key "creationix"
users.save("creationix", {name: "Tim Caswell", age: 29}, function (err) {
    if (err) { throw err; }
    // The save is finished and written to disk safely
});

// Or insert with auto key
users.save(null, {name: "Bob"}, function (err, key) {
    if (err) { throw err; }
    // You now have the generated key
});

Loading a document

Assuming the previous code was run, a file will now exist with the persistent data inside it.

// Load the document with the key "creationix"
users.get("creationix", function (err, doc, key) {
    if (err) { throw err; }
    // You now have the document
});

Removing a document

Remove is by key only.

// Remove our new document
users.remove("creationix", function (err) {
    if (err) { throw err; }
    // The document at key "creationix" was removed
});

Clearing the whole collection

You can also quickly clear the entire collection

// Clear
users.clear(function (err) {
  // The database is now empty
});

This clears all the keys and triggers a compaction. Only after the compact finishes is the data truly deleted from the disk, however any further queries cannot see the old data anymore.

Querying the database

There are no indexes, however, nStore provides a simple query interface to get at data quickly and easily. You can filter using condition expressions or plain functions.

To use queries, you need to include the query addon.

var nStore = require('nstore');
nStore = nStore.extend(require('nstore/query')());

Query as a single callback

For convenience you can pass in a callback and get the results as a single object.

// Using a callback for buffered results
users.find({age: 29}, function (err, results) {
  // results is an object keyed by document key with the document as the value
});

Query using streams.

Also you can stream results.

var stream = users.find({age: 29});
stream.on("document", function (doc, key) {
  // This is a single document
});
stream.on("end", function () {
  // No more data is expected
})

all shortcut

If you want no condition you can use the all() shortcut.

users.all(function (err, results) {
  // All the users are now in a single object.
});

Structure of condition expressions.

A simple condition is pairs of key's and values. This builds a condition where all columns named by the key must equal the corresponding value.

This matches rows where name is "Tim" and age is 29:

{name: "Tim", age: 29}

If a key contains space, then the operator after it is used instead of equal.

This matches rows where age is greater than 18 and age is less than 50:

{"age >": 18, "age <": 50}

The supported operators are:

  • < - less than
  • <= - less than or equal to
  • >= - greater than or equal to
  • > - greater than
  • != or <> - not equal to

If an array of hash-objects is passed in, then each array item is grouped and ORed together.

This matches name is "Tim" or age < 8:

[{name: "Tim"}, {"age <": 8}]

Special compaction filter

There are times that you want to prune stale data from a database, like when using nStore to store session data. The problem with looping over the index keys and calling remove() on them is that it bloats the file. Deletes are actually appends to the file. Instead nStore exposes a special filter function that, if specified, will filter the data when compacting the data file.

// Prune any items that have a doc.lastAccess older than 1 hour.
var session = nStore.new('data/sessions.db', function () {
  // It's loaded now
});
session.filterFn = function (doc, meta) {
  return doc.lastAccess > Date.now() - 360000;
};

nstore's People

Contributors

creationix avatar pita avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nstore's Issues

find / get fail

Sorry to disturb you once again :P

But i'm just trying to help out by bringing out the bugs. Both getting the document and finding the documents work well if the program is in memory and running. I'm guessing this is because the indices are available in the memory. My problem arises when i try to get the record based on the key or try to find it.

using get -> Document does not exist.
using find-> returns an empty array in the result.

I'm probably making a big mistake here, if so could you be kind enough to point out the problem?
Thanks in advance.

can only access document properties using bracket syntax and not '.' syntax

I am trying to access the document properties with a closure variable

var sys = require('sys');
var nstore = require('nstore');
var name;
var users = nstore('users.db')
users.save('creationix', {name: 'creationix', password: 'password'});
// when I check users.db, this record is there

users.get('creationix', function(err, doc, meta) { 
    name = doc.name;
    sys.puts(name);
    //displays name "creationix"
});

// some time later

sys.puts(name);
// returns undefined

it does work if I do this

name = doc[name];

why is this?

nstore module not loading

var nStore = require('nstore'); --> leads to the following error -->
"node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Cannot find module 'nstore'
at Function._resolveFilename (module.js:322:11)
at Function._load (module.js:267:25)
at require (module.js:351:19)
at Object. (/home/gaara/workspace/powercuts/datacruncher.js:1:76)
at Module._compile (module.js:407:26)
at Object..js (module.js:413:10)
at Module.load (module.js:339:31)
at Function._load (module.js:298:12)
at Array. (module.js:426:10)
at EventEmitter._tickCallback (node.js:126:26)"

Any idea what the problem is ? Every other module loads just fine without a problem.

Thanks in advance

Object #<an Object> has no method 'find'

Am I doing something wrong?

var nStore = require('nstore');
var users = nStore.new(__dirname+'/users.db', function () {
  users.save("creationix", {name: "Tim Caswell", age: 28}, function (err) {
    if (err) { throw err; }
  });
  users.find({age: 28}, function (err, results) {
    if (err) { throw err; }
    else { console.log(results); }
  });
});

Throws an error

node.js:50
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Object #<an Object> has no method 'find'
at /mnt/dev/test/nstore.test.js:26:9
at Array.<anonymous> (/home/patrick/.node_libraries/.npm/nstore/0.3.0/package/lib/nstore.js:94:49)
at EventEmitter._tickCallback (node.js:42:22)
at node.js:634:9

nstore.new callback called twice

using express+coffescript:

projects = store.new 'projects.db', ->
    app.listen 3000, 'localhost'

the callback is called twice. Is this a bug?

(a side-effect of that is that projects seems to refer to the wrong object, I can't call projects.all == undefined)

How to user ur module for user of my site

I want to use your module for the storing users info of my site , e..g username password etc.

So implementing that i got one issue is that it create the new db every time restart :

// Create a store
var users = nStore.new('data/users.db', function () {
// It's loaded now
});

So how can i load already created db .and retain my data .Please suggest .

installing nstore

  1. suggestion : can you tell why not step.js is included in your git. need to install seperately.
  2. where i can find the pattern module.

get result from users.find() function

Hi!
I have the code:

var sys = require('sys');
var nStore = require('nstore/lib/nstore').extend(require('nstore/lib/nstore/query')());
var users = nStore.new('data/users.db', function (){
users.find({user: "alex", pass:"123"}, (function(err, results) {
if(err) {
sys.puts('not found...');
}
else
{
sys.puts(results.creationix.room);
}
}));
});

What I need is something like:

var sys = require('sys');
function routeToRoom(userId,passw){
var roomId=0;
var nStore = require('nstore/lib/nstore').extend(require('nstore/lib/nstore/query')());
var users = nStore.new('data/users.db', function (){
users.find({user: userId, pass:passw}, (function(err, results) {
if(err) {
roomId=-1;
}
else
{
roomId=results.creationix.room;
}
}));
});
return roomId;
}
sys.puts(routeToRoom("alex","123"));

But I get always: 0

I guess "return roomId;" is executed before that " roomId=results.creationix.room;" . Could someone help me whit this code?
Thanks in advance!

Is this project still alive?

I really love the concept of nstore and it's just what I need. Is this still usable with node 0.10 as it hasn't been updated anymore in the past 2 years?

TypeError: Object #<initialize> has no method 'loadDatabase'

I'm new to Node.js, but I'm sure I installed this module correctly using npm 1.0.5 on node 0.4.7. However, when I try the examples, I get TypeError: Object # < initialize > has no method 'loadDatabase'.

Is it incompatible w/ 0.4.7 or is there something else I need to do to fix this?

clear() doesn't do anything

I might be misleading on the semantic of clear, but it seems it doesn't do anything (at least when this is the first operation applied on a newly loaded store). Shouldn't it empty the store?

Broken with new npm 0.3.9

When I install nStore with npm it seems to install fine. However, when I require('nstore'), node tells me the module cannot be found.

3gb in size to the database

hi @creationix,

I'm thinking of using it in my application, today it has a database with 3GB.

You believe that nstore can running with this amount of data in a good way?

msgpack

Hi!

Wonder if you could consider using msgpack as store format?

TIA,
--Vladimir

add some kind of 'find' wrapper ?

It would be handy to have a shortcut for the find stuff. E.g. something like

users.find(function(doc, meta) {
   return doc.age > 18 && doc.age < 40;
}, function(results) { 
  // Do something with all the documents
})

no method `find` nor `all`

The documentation references find and all methods, but it appears that you have to extend the db object with them yourself.

Except that you can't do that either:

TypeError: Can't add property all, object is not extensible

What is the best practice ? (beginner question)

Hello
I wish I knew what was best if I make an application with Express (for example) :

  • i need a "model"
  • i need to save each instance of model

do I have to, every time I save, do a :

var mystore = nStore.new("data/blog.db", function() {
    mystore.save(null, myModel, function(err, key){ ... });
});

or I declare, initially, a global variable (for example) then I use in my modelsUndo edits :

global.blogStore = nStore.new("data/blog.db", function() {
    app.get('/add',function(req, res){

        var model_from_client = JSON.parse(req.param("model", null));       
        var post = new Post(model_from_client.title, model_from_client.message);

        post.save(function(key){
            console.log("Post added with key : ", key)
        });

    });

    app.listen(3000);
    console.log('Express app started on port 3000');    
});

and with :

var Post = function (title, message) {
    this.title = title ? title : "";
    this.message = message ? message : "";

    this.save = function(callback) {
        blogStore.save(null,this,function(err, key){
            callback(key, err);
        });
    }
}

thank you

rql

Hi!

We've been developing a common feature-rich Resource Query Language: http://github.com/kriszyp/rql. Couldn't you review the opportunity to incorporate it as nStore query syntax?

TIA,
--Vladimir

loadDatabase fails with an error in Buffer module "targetStart out of bounds"

Loading Database into buffers when it is a little bigger than 2.0 KB is buggy. here is stack trace:

Error: targetStart out of bounds
at Buffer.copy (buffer.js:366:11)
at loadDatabase (/usr/local/lib/node/.npm/nStore/0.2.1/package/lib/nstore.js:202:13)
at nStore (/usr/local/lib/node/.npm/nStore/0.2.1/package/lib/nstore.js:243:3)

I think shifting the input back down as you commented in nstore.js cause this bug.

error when trying to create a store

node v0.3.3
nstore v0.3.0

node.js:68
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Object # has no method 'loadDatabase'
at new initialize (/usr/local/lib/node/.npm/nstore/0.3.0/package/lib/nstore.js:28:10)
at Object.anonymous (eval at extend (/usr/local/lib/node/.npm/pattern/0.1.0/package/lib/pattern.js:24:56))
at Object. (/home/nick/dev/pad/device/http.js:7:22)
at Module._compile (node.js:360:32)
at Object..js (node.js:368:14)
at Module.load (node.js:291:27)
at Array. (node.js:382:26)
at EventEmitter._tickCallback (node.js:60:24)

"results is an object keyed by document key with the document as the value"

Hi!
First of all, thank you for your project I think will be util!
Look, My simple question is: What is the format to get the value as result of the find command? That's, What do I need to write in "sys.puts(result....)" command to get the age for example?
Thank you in advance!

users.find({name: "profesoralex"}, function(err, results) {
// results is an object keyed by document key with the document as the value
sys.puts(results["creationix"].key.name);
});

Broken with express+connect+nstore-session

Here is a terrible bug in nStore. When used together with express, and nstore-session it somehow manages to create a wrong index for the database, which leads to invalid JSON exceptions being thrown.

Here is an example. This database was created by nstore-session:

{"lastAccess":1284315882938}    {"key":"df4e2e9f03e00ae7657823ff2c1a.6c069e863cf2262ec95d8cfe5dac2d47"}
{"lastAccess":1284315883048}    {"key":"df4e2e9f03e00ae7657823ff2c1a.6c069e863cf2262ec95d8cfe5dac2d47"}
    {}
{"lastAccess":1284315889592,"name":"pkrumins"}  {"key":"dccae3e52ec5ef3f584aea9df1bb.6f58e178ddc813ae35b84c665a58ec8b"}

And when used, nStore would throw the following error:

SyntaxError: Unexpected token ILLEGAL
    at Object.parse (native)
    at /usr/local/pkg/nodejs-0.2.0/lib/node/.npm/nStore/0.2.1/package/lib/nstore.js:103:27
    at /usr/local/pkg/nodejs-0.2.0/lib/node/.npm/nStore/0.2.1/package/lib/nstore.js:33:7
    at node.js:764:9

So I debugged it and located that when it requests the last key 'dccae3e52ec5ef3f584aea9df1bb.6f58e178ddc813ae35b84c665a58ec8b', the index it uses to read the record from the db file is messed up:

{ position: 279
, length: 46
, meta: { key: 'dccae3e52ec5ef3f584aea9df1bb.6f58e178ddc813ae35b84c665a58ec8b' }
}

The contents in the db at position 279 is:

4aea9df1bb.6f58e178ddc813ae35b84c665a58ec8b"}

At line 101 nStore tries to call JSON.parse(buffer.toString()); and this buffer.toString() is the data above. So it throws an exception that I listed.

Here is how to reproduce. Clone StackVM at this revision:
http://github.com/substack/stackvm/commit/fa702d45234532b7bacc572e08676f4b74627cd0

Next run node ./stackvm/bin/populate.js to populate users database.

Then run node ./stackvm/server.js to start StackVM locally.

Then connect to localhost:9000 and use pkrumins as login and moo as password. That will log you into StackVM.

Now in the console you should see SyntaxError: Unexpected token ILLEGAL. Also if you now press logout, express will catch this exception and display it in the browser. But you'll also see it in the console.

I hope you can locate this bug, I spent a lot of time debugging it but could not determine what caused it. If you just simply took the database I listed there above (and replace 4 spaces between records with tabs), it would work. Doesn't work just in the web environment.

Issue with get all function right after saving an object to DB

Right after I save my object to DB, I refresh my view and I get the following value error
instead of getting the object attributes as I designed. Everything seems OK in the db file itself, and if I restart my node application I start getting the right string. This event only occurs after I insert something to DB and before restarting the application.

Saving same key twice creates 2 data rows rather than updating existing key

Hi, If I am attempting to "update" a row of data...if I get a document, then change it and attempt to save it again using the same key....it simply adds a new record to the flat file database. Over time, this causes the flat file database to become huge and unmanageable. I would like a way to update a data row by key that does not cause data to be created needlessly.

Length extends beyond buffer

Hi, I'm storing results of Google Maps Places search and also Facebook Places into nStore.
But after some time I get following error:

version of nStore: 0.5.2

fs.js:457
  binding.read(fd, buffer, offset, length, position, wrapper);
          ^
Error: Length extends beyond buffer
    at Object.fs.read (fs.js:457:11)
    at readChunk (/private/var/www/myapp-nodejs/node_modules/nstore/lib/file.js:18:8)
    at fsRead (/private/var/www/myapp-nodejs/node_modules/nstore/lib/file.js:30:3)
    at checkQueue (/private/var/www/myapp-nodejs/node_modules/nstore/lib/file.js:63:5)
    at /private/var/www/myapp-nodejs/node_modules/nstore/lib/file.js:66:9
    at /private/var/www/myapp-nodejs/node_modules/nstore/lib/file.js:27:7
    at Object.wrapper [as oncomplete] (fs.js:454:17)
DEBUG: Program node server.js exited with code 8

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.