Separated sections of LevelUP.
SublevelUP models "sublevel" as separated table sections, providing idiomatic mapping to both key prefix sublevels and table based backends.
SublevelUP is a "subclass" of LevelUP, which means full compatibility with latest LevelUP interface.
npm install sublevelup
The "standard" way of creating sublevels.
Given the fact that LevelDB stores entries lexicographically sorted by keys, it is possible to creating a "sandboxed" section using ranged key prefix. Unlike separated LevelDB instances, atomic batched write works across sublevels, which is an important primitive for consistency.
SublevelUP encodes key prefix using !
padding with #
separator. That means nested sublevels are also separated.
var level = require('level')
var sublevel = require('sublevelup')
//Key-prefix: passing LevelUP to Sublevel
var db = sublevel(level('./db')) //prefix !!
var hello = sublevel(db, 'hello') //prefix !hello!
var foo = db.sublevel('foo') //prefix !foo!
var fooBar = sublevel(foo, 'bar') //prefix !foo#bar!
var fooBarBla = fooBar.sublevel('bla') //prefix !foo#bar#bla!
The prefix approach, while a good fit for LevelDB, ill-suited for using SQL database as a LevelUP backend. Concatenating every sublevels into one single table is not ideal for B-tree index that most SQL database uses. There is also no reason not to utilise tables since they serve the exact same purpose.
SublevelUP provides idiomatic mapping to tables based LevelDOWN modules where location
argument defines the table DOWN(table)
.
Atomic batched write works across table-based sublevels, given most SQL databases support transactions across tables.
Table prefix are encoded using _
separator.
MyDOWN for example, a MySQL backend suits well as a table-based sublevel.
var sublevel = require('sublevelup')
var mydown = require('mydown')('db', {
host: 'localhost',
user: 'root',
password: 'secret'
})
//Table-based: passing LevelDOWN to Sublevel
var db = sublevel(mydown) //table _
var hello = sublevel(db, 'hello') //table hello
var foo = db.sublevel('foo') //table foo
var fooBar = sublevel(foo, 'bar') //table foo_bar
var fooBarBla = fooBar.sublevel('bla') //table foo_bar_bla
batch()
is a transactional operation that works across sublevels, by setting the prefix: sub
property.
var db = sublevel(mydown)
var a = db.sublevel('a')
var b = db.sublevel('b')
// batch from a
a.batch([
{ type: 'put', key: 'foo', value: 'a' },
{ type: 'put', key: 'foo', value: 'b', prefix: b }, //put into b
], function () {
a.get('foo', function (err, val) { }) // val === 'a'
b.get('foo', function (err, val) { }) // val === 'b'
})
It is possible to create custom codec for sublevel prefix or table name by passing options.prefixEncoding
for encode/decode function,
such as bytewise:
var level = require('level')
var sublevel = require('sublevelup')
var bytewise = require('bytewise-core')
var codec = {
encode: function (arr) {
return bytewise.encode(arr).toString('binary')
},
decode: function (str) {
return bytewise.decode(new Buffer(str, 'binary'))
}
}
//Key-prefix Sublevel with custom codec
var db = sublevel(level('./db'), { prefixEncoding: codec })
Sublevel inherits methods of LevelUP plus following:
db
is a
- LevelUP instance for key-prefix sublevel
- LevelDOWN constructor for table-based sublevel
- Sublevel instance for nesting sublevel under
name
Nesting sublevel under name
.
MIT