robe
v2.1.0
Published
MongoDB ODM for Node.js using ES6 generators. Supports schema validation, cursors, oplog tailing, etc.
Downloads
50
Maintainers
Readme
Robe
Robe wraps around monk to provide a simple yet effective ODM library for MongoDB.
Features:
- Work with ODM-style documents or raw Mongo data - the choice is yours
- Add before and after hooks for inserts, updates and removals
- Cursor mode (for streaming results)
- Schema validation (simple-nosql-schema).
- Indexes and replica sets supported
- Mongo oplog tailing (like in Meteor)
- and more...
Installation
This package requires Node 4+
$ npm install robe
Examples
Detailed documentation is available at https://hiddentao.github.io/robe.
The basics
"use strict";
var co = require('co'),
Robe = require('robe');
co(function*() {
// connect to db
var db = yield Robe.connect('127.0.0.1');
// get a collection
var collection = db.collection('test');
// insert a record
yield collection.insert({
name: 'jim',
age: 23
});
// find it
var item = yield collection.findOne({
name: 'jim'
});
console.log(item instanceof Robe.Document); // true
console.log(Object.keys(item)); // _id, name, age
// update
item.age = 54;
yield item.save(); // internally calls collection.update(...)
// remove
yield item.remove(); // internally calls collection.remove(...)
})
.catch(function(err) {
console.error(err);
});
Raw querying mode
In this mode we won't make use of Robe.Document
and will instead deal
directly with Mongo data objects.
// insert a record
yield collection.insert({
name: 'jim',
age: 23
});
// find it
var item = yield collection.findOne({
name: 'jim'
}, {
rawMode: true // return the raw mongo object
});
console.log(item instanceof Robe.Document); // false
console.log(Object.keys(item)); // _id, name, age
// update
yield collection.update({
_id: item._id
}, {
$set: {
age: 54
}
});
// remove
yield collection.remove({
_id: item._id
});
You can also enable rawMode
querying at the collection level:
var collection = db.collection('test', {
rawMode: true
});
yield collection.findOne({
name: 'john'
}, {
rawMode: false // override the collection-level setting
});
Hooks
You can add multiple before
and after
hooks for insertions, updates and
removals. Hooks get triggered even when calling the save()
and remove()
methods on a Robe.Document
instance.
collection.before('remove', function*(search, next) {
console.log('Before hook');
search.age = 54;
console.log(JSON.stringify(search));
yield next;
});
collection.after('remove', function*(search, result, next) {
console.log('After hook: ' + result);
yield next;
});
// remove
yield collection.remove({
name: 'john'
});
/*
Ouptut:
Before hook
{ name: 'john', age: 54 }
After hook: 1
*/
Schema validation
Schema definitions are as supported by simple-nosql-schema. Inserts and updates trigger schema validation checks. Any keys not specified in the schema get ignored during validation, i.e. a schema can be a partial definition of a document.
// get a collection
var collection = db.collection('test', {
schema: {
name: {
type: String
},
isMarried: {
type: Boolean
},
numCars: {
type: Number
},
}
});
// insert a record
try {
yield collection.insert({
name: 'jim',
hasKids: true,
isMarried: 'yes',
numCars: '20'
});
} catch (err) {
console.log(err);
/*
Error: Validation failed
*/
console.log(err.failures);
/*
[
"/isMarried: must be true or false",
"/numCars: must be a number",
]
*/
}
Indexes
Robe supports the full Mongo index spec and can ensure that indexes you define are present within a collection:
// get a collection
var collection = db.collection('test', {
indexes: [
// each entry in this array represents an index in the collection
{
fields: {
name: -1
},
options: {
unique: true
}
},
{
fields: {
name: 1,
age: 1,
},
options: {
name: 'index2'
}
},
]
});
// setup all indexes
yield collection.ensureIndexes();
Oplog tailing
If you are connecting to a Mongo replica set, then you can tail the oplog through Robe, allowing you to be notified when collections within your database get updated (even by other processes).
// connect to replica set
// (note that replicaSet parameter MUST be set to actual replica set name)
var db = yield Robe.connect([
'127.0.0.1/dbname?replicaSet=example',
'127.0.0.2/dbname?replicaSet=example',
]);
var collection = db.collection('test');
// watch for any changes to the collection
yield collection.addWatcher(function(collectionName, operationType, data) {
// collectionName = collection which got updated
// operationType = one of: insert, update, delete
// data = the data which got inserted or updated
});
/* you can also access the oplog directly on the `db` */
// get the oplog
var oplog = yield db.oplog();
// start it
yield oplog.start();
// listen for any operation on any collection
oplog.onAny(function(collectionName, operationType, data) {
// ...
});
// listen for any operation on the "test" collection
oplog.on('test:*', function(collectionName, operationType, data) {
// ...
});
// listen for delete operations on the "test" collection
oplog.on('test:delete', function(collectionName, operationType, data) {
// ...
});
Building
To run the tests:
$ npm install -g gulp
$ npm install
$ npm test
Contributing
Contributions are welcome! Please see CONTRIBUTING.md.
Inspiration and thanks
License
MIT - see LICENSE.md