level-assoc

relational foreign key associations (hasMany, belongsTo) for leveldb

level-assoc

foreign key associations (hasMany, belongsTo, ...) for leveldb

example

var sub = require('level-sublevel');
var level = require('level-test')();
var db = sub(level('test', { valueEncoding: 'json' }));
 
var assoc = require('level-assoc')(db);
assoc.add('hackerspace')
    .hasMany('hackers', [ 'type', 'hacker' ])
    .hasMany('tools', [ 'type', 'tool' ])
;
assoc.add('hacker').belongsTo('hackerspace');
assoc.add('tool')
    .hasMany('usage', [ 'type', 'usage' ])
    .belongsTo('hackerspace')
;
 
db.batch(require('./data.json').map(function (row) {
    return { type: 'put', key: row.key, value: row.value };
}), ready);
 
function ready () {
    assoc.get('sudoroom', function (errroom) {
        console.log('SUDOROOM=', room);
        room.hackers().on('data', function (r) {
            console.log('HACKER', r.value)
        });
    });
 
    assoc.get('8d9a83', function (errtool) {
        console.log('TOOL=', tool);
        tool.usage().on('data', function (r) {
            console.log('USAGE', r.value)
        });
    });
}

given this data.json in the database:

[
  {"key":"sudoroom","value":{"type":"hackerspace","name":"sudoroom"}},
  {"key":"noisebridge","value":{"type":"hackerspace","name":"noisebridge"}},
  {"key":"substack","value":{"type":"hacker","name":"substack","hackerspace":"sudoroom"}},
  {"key":"maxogden","value":{"type":"hacker","name":"maxogden","hackerspace":"sudoroom"}},
  {"key":"ioerror","value":{"type":"hacker","name":"ioerror","hackerspace":"noisebridge"}},
  {"key":"mitch","value":{"type":"hacker","name":"mitch","hackerspace":"noisebridge"}},
  {"key":"wrought","value":{"type":"hacker","name":"wrought","hackerspace":"sudoroom"}},
  {"key":"mk30","value":{"type":"hacker","name":"mk30","hackerspace":"sudoroom"}},
  {"key":"8d9a83","value":{"type":"tool","name":"3d printer","hackerspace":"sudoroom"}},
  {"key":"ea7e66","value":{"type":"tool","name":"piano","hackerspace":"sudoroom"}},
  {"key":"025452","value":{"type":"tool","name":"laser cutter","hackerspace":"noisebridge"}},
  {"key":"yardena","value":{"type":"hacker","name":"yardena","hackerspace":"sudoroom"}},
  {"key":"5cc709","value":{"type":"tool","name":"3d printer","hackerspace":"noisebridge"}},
  {"key":"d06ab1","value":{"type":"usage","tool":"8d9a83","minutes":"45","user":"maxogden"}},
  {"key":"2454c1","value":{"type":"usage","tool":"8d9a83","minutes":"20","user":"yardena"}},
  {"key":"ec08ed","value":{"type":"usage","tool":"ea7e66","minutes":"14","user":"substack"}},
  {"key":"61baab","value":{"type":"usage","tool":"025452","minutes":"8","user":"mitch"}}
]

the program prints:

SUDOROOM= { type: 'hackerspace',
  name: 'sudoroom',
  hackers: [Function],
  tools: [Function] }
TOOL= { type: 'tool',
  name: '3d printer',
  hackerspace: 'sudoroom',
  usage: [Function] }
HACKER { type: 'hacker', name: 'maxogden', hackerspace: 'sudoroom' }
USAGE { type: 'usage', tool: '8d9a83', minutes: '20', user: 'yardena' }
HACKER { type: 'hacker', name: 'mk30', hackerspace: 'sudoroom' }
USAGE { type: 'usage', tool: '8d9a83', minutes: '45', user: 'maxogden' }
HACKER { type: 'hacker', name: 'substack', hackerspace: 'sudoroom' }
HACKER { type: 'hacker', name: 'wrought', hackerspace: 'sudoroom' }
HACKER { type: 'hacker', name: 'yardena', hackerspace: 'sudoroom' }

methods

var levelAssoc = require('level-assoc')

Create a new assoc instance from a sublevel-enabled leveldb instance db.

Fetch a key from the database with cb(err, row). row contains the underlying db.get() result but augmented with functions to return streams for the has-many collections.

Create a new type association t for rows with a "type" field set to name.

Create a streaming collection at key for foreign rows matching the string array path filterKey.

TODO. Currently a no-op.

install

With npm do:

npm install level-assoc

license

MIT