Skip to content
/ robe Public

MongoDB ODM for Node.js using ES6 generators. Supports schema validation, raw querying, oplog tailing, etc.

License

Notifications You must be signed in to change notification settings

hiddentao/robe

Repository files navigation

Robe

Build Status NPM module NPM downloads Follow on Twitter

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

About

MongoDB ODM for Node.js using ES6 generators. Supports schema validation, raw querying, oplog tailing, etc.

Resources

License

Stars

Watchers

Forks

Packages

No packages published