Bluebird aware mongoDB driver.
Install the module via npm:
npm install mongobird
This simple example connects to a mongoDB instance, gets a specific database and collections and uses this collection to add data and assert that it worked:
var mongobird = require('mongobird'),
connectionString,
connection,
anyDb,
usersCollection;
// The connection string specifies which mongoDB instance should be used
connectionString = 'mongodb://localhost';
// Create a connection representation using a connection string
connection = mongobird.connect(connectionString);
// Get a representation for any database through the mongoDB instance from above
anyDb = connection.getDb('anyDb');
// Get any collection through this database representation
usersCollection = anyDb.getCollection('users');
function logAddedUser(user) {
console.log('Added user ' + user.username);
}
function countUser(username) {
return usersCollection.count({ username: username });
}
// Note that all the methods used before this were working lazily - they did not really connect to any database
usersCollection.insert({ username: 'anyUser' })
.tap(logAddedUser)
.then(countUser.bind(null, 'anyUser')
.then(function (count) {
if (count !== 1) {
throw new Error('User was not added correctly or exists more than once');
}
})
.catch(function(error) {
console.log('Handle errors or rethrow them if you are not able to');
});
As mentioned above, it is important to understand, that the database and collection representations are not connecting to any specific database or collection before they are really used (e.g. for inserting data). One consequence of this is that errors accessing these databases or collection (e.g. for not existing databases) will be thrown later when the collection or database are really used.
See the more detailed "explained example" below for a better understanding how everything works.
This is a more complex example. See the notes below it to understand how it works internally.
'use strict';
var mongobird = require('mongobird'),
connectionString = 'mongodb://localhost',
connection = mongobird.connect(connectionString),
anyDb = connection.getDb('anyDb'),
usersCollection = anyDb.getCollection('users'),
defaultUser = { username: 'anyUser' },
demoFinishedMessage = 'Demo finished succesfully. Have fun using mongobird';
function findDefaultUser() {
return usersCollection.findOne(defaultUser);
}
function assertDefaultUserDoesNotExist(user) {
if (user) {
throw new Error('Default user already exists');
}
}
function removeUser(user) {
console.log('Removing user:', user);
return usersCollection.remove({ username: user.username });
}
module.exports = function () {
return usersCollection.remove({})
.then(findDefaultUser)
.then(assertDefaultUserDoesNotExist)
.then(usersCollection.insert.bind(null, defaultUser))
.tap(function (addedUsers) {
if (addedUsers.length !== 1) {
throw new Error('Not the right amount of users were added');
} else if (addedUsers[0].username !== defaultUser.username) {
throw new Error('Added user was not the default user');
}
console.log('Added default user:', defaultUser.username);
})
.then(findDefaultUser)
.then(function (user) {
if (!user) {
throw new Error('Default user does not exist');
}
return user;
})
.then(removeUser)
.then(function () {
throw new Error('Something bad happened');
})
.then(console.log.bind(null, 'This is not executed if there is an uncaught error'))
.catch(console.log.bind(null, 'Catching error'))
.then(console.log.bind(null, 'Error was handled in last catch step'))
.return(demoFinishedMessage)
.finally(function () {
// E.g. close the database connection
});
};
Create a connection representation using the connect
method providing a valid connection string (as specified in
the mongoDB documentation about connection strings
connection = mongobird.connect(connectionString);
The connect
method is a synchronous function. The reason for this is that mongobird
connects to mongodb
instances lazily and caches the used database connections once they are established.
The returned connection
object has the important method getDb
which takes a database name and returns a database
representation. The method works synchronous and does not connect to the database instantly but saves only the required
data to connect to it later.
anyDb = connection.getDb('anyDb');
This returned database representation can be used to work on mongoDB collections. All
[collection methods provided by the native mongoDB driver]
(http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html) are available and return bluebird
Promises.
Using one of these methods triggers a real connection to the specified mongo database.
usersCollection = anyDb.getCollection('users');
The most interesting part happens on this collection representation - some of the more common mongoDB methods are called and all is done using promises
See the general bluebird documentation to learn more about promises
in general and how bluebird
promises help you writing better readable, understandable and good-looking (in the
opinionated view of the creators of this library) way
Read the more specific bluebird api documentation
to get used more specifically to the bluebird
methods. E.g. you can find documentation on the very useful methods
Promise.tap
and Promise.try
that were used in the example above
One further very good read recommendation is the [documentation about promise anti-patterns] (https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns)
mongobird.connect
method provides a connection representation
connection = mongobird.connect(connectionString);
connection representation
can be used to get a database representation
database = connection.getDb(databaseName);
database representations
can be used to get collection representations
collection = database.getCollection(collectionName);
These collection representations
are a central part of mongobird
(as they are in the native mongoDB driver). They
offer all [collection methods provided by the native mongoDB driver]
(http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html) with one difference: The methods in the native
driver rely on callbacks to handle what is done once they are finished. As mongobird
works with promises this looks
differently for them. Examples:
insert
: Instead of calling collection.insert(document, callback)``js
collection.insert(document)
.then(function (result) { ... })
.catch(function (error) { ... });
* `find`:
```js
collection.find(document)
.then(function(foundDocuments) { ... } )
.catch(function (error) { ... });
remove
:collection.remove(document)
.then(function (result) { ... })
.catch(function (error) { ... });
This project is in a very early state and many planned features are missing for now.
Nevertheless there is some interesting additional information: