modella-sublevel
v1.0.0-beta.2
Published
Modella plugin to attach a model to a `sublevel`-based backing store, with optional secondary indexing
Downloads
4
Maintainers
Readme
modella-sublevel
Modella plugin to attach a model to a sublevel
-based backing store, with optional secondary indexing.
Usage
var sublevel = require('modella-sublevel')
var MyModel = model('MyModel')
.use(sublevel)
// primary key field required (defaults to `id` or `_id` attr per modella API
.attr('mykey', {
primaryKey: true
})
// unindexed attribute
.attr('somefield', {
defaultValue: 'xxx'
})
// explicitly indexed field
.attr('indexedfield', {
index: true
})
// unique fields are implicitly implicitly indexed to verify uniqueness
.attr('uniquefield', {
unique: true
})
// model initialized, but saving instances will throw until store is attached
var model = new Model({
mykey: 'a',
// unique fields are inherently `required: true`
uniquefield: 'foo'
})
model.save(function(err, model) {
err.message === 'No store available'
})
Attaching a store
// some time later, assuming `db` is in scope...
var store = db.sublevel('MyModel')
// attach new sublevel as backing store for our model
MyModel.attach(store)
// now we can save model instances
model.save(function (err, model_) {
// no error this time
err == null
// callback is invoked with the same instance of model
model_ === model
})
Model-aware store methods
// the backing store is made available on the `store` key
MyModel.store === store
// store methods are overriden to do model creation/validation
myStore.put('b', {
// id will be set to `primaryKey` field defined by model
uniquefield: 'bar'
}, function (err, record) {
// `store.put` overridden to return created JSON record
record.key === 'a'
// this will include any attributes generated by model instantiation
record.somefield === 'xxx'
})
Store-aware model methods
// modella API extended with some static convenience methods
MyModel.create({
mykey: 'c',
uniquefield: 'baz'
}).save(err, model) {
// again, result of save is a model instance, which we can manipulate
model.somefield('yyy')
model.save(function (err) {
// our changes are now persisted
})
})
// convenient static methods are available for interfacing with the store
MyModel.add({
// ensures key is new
mykey: 'd',
uniquefield: 'quux'
})
// query by primary key (if `createReadStream` available on sublevel)
Model.query({ gt: 'b' }).on('data', function (model) {
// invoked with model instances
model.primary() >= 'b'
})
// query on a secondary index explicitly (if supported by sublevel)
Model.query.uniquefield({ gt: 'bar' }).on('data', function (model) {
model.uniquefield() > 'bar'
})
// observe changes on an indexed attribute (if `createLiveStream` avaialable)
Model.tail.indexedfield().on('data', function (data) {
if (data.type !== 'del') {
// data.model.get('indexedfield')
}
})
Detaching a store
The attach
method can be called without a store reference to detach store from model:
OtherModel.attach()
OtherModel.store === undefined
When detaching, any methods overwritten on the backing store instance will be replaced with their original versions.