npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mongodb-next

v0.8.0

Published

A fluent Promise and Streams2 MongoDB API wrapper

Downloads

26

Readme

mongodb-next

NPM version Build status Test coverage Dependency Status License Downloads Gittip

A MongoDB API wrapper with:

  • A fluent, chaining API without traditional MongoDB drivers and wrappers' function varity and long names
  • Streams2 support with proper .destroy() calls
  • Promise support
  • Supports node-mongodb-native v1 as well as v2.
  • MongoDB 2.6+ support
    • Aggregation framework support
    • Bulk write support

Note: tests currently fail on Travis because Travis uses MongoDB 2.4

All methods return promises, so your code now looks like this:

var wrap = require('mongodb-next').collection
var collection = wrap(db.collection('test'))

var batch = collection.batch() // ordered batched writes
batch.insert({ a: 1 })
batch.insert({ b: 2 })
batch.then(function () {
  return collection.findOne('a', 1).readPreference('secondaryPreferred')
}).then(function (doc) {
  return collection.findOne(doc._id).update('a', 2).w('majory')
})

Or the new way:

var DB = require('mongodb-next');
var db = DB('mongodb://localhost/test', {
  w: 'majority'
});

db.connect.then(function () {
  db.collection('things').find({
    name: 'jon'
  }).then(function (things) {
    console.log(things)
  })
})

Or if you use something like co:

co(function* () {
  var batch = collection.batch()
  batch.insert({a: 1})
  batch.insert({b: 2})
  yield batch
  var doc = yield collection.findOne('a', 1).readPreference('secondaryPreferred')
  var doc2 = yield collection.find(doc._id).updateOne('a', 2).w('majory').new()
}).catch(function (err) {
  console.error(err.stack)
  process.exit(1)
})

Context

Christian, the maintainer of node-mongodb-native, is interested in a version of the MongoDB driver that supports native promises as well as other ES6+ features. However, this won't remotely be a possibility until after v3.0 of the driver is out.

I expressed my interest in creating a well defined API, and this is what I consider ideal. As Christian is refactoring the driver, this may, in the future, be an alternative API. The goal is for this API to last past ES7, where code will look like:

async function run() {
  var docs = await collection.find({
    name: 'jon'
  })
}

run.catch(function (err) {
  console.error(err.stack)
  process.exit(1)
})

Compatibility

This library uses promises extensively. Currently, it uses bluebird, but it will eventually switch to native promises.

This library also only supports MongoDB 2.6+, but most commands will still work with MongoDB 2.4 and any MongoDB driver that shims various 2.6 commands for 2.4.

This library supports node-mongodb-native@1 as well as @2.

API

var DB = require('mongodb-next');

var db = DB(uri, [options])

Create a new db instance from a URI w/ options. A wrapper around MongoClient.connect()

db.connect.then( => )

Wait until the database is connected. Use this before doing any subsequent commands.

db.raw

The raw database connection provided by MongoDB.

wrap(collection)

The primary constructor wraps a MongoDB Collection. This is the same as doing db.collection(name).

var wrap = require('mongodb-next').collection
var collection = wrap(db.collection('test'))

// or
var db = DB('mongodb://localhost/test');
db.connect.then(function () {
  var collection = db.collection('test')

  // can now do;
  db.test.find({
    name: 'test'
  })
})

Entry Points

Only a few methods are available on collection itself:

  • .find() - for searching or updating multiple documents
  • .findOne() - for searching or updating a single document
  • .insert() - for inserting documents
  • .remove() - remove documents, shortcut for .find().remove()
  • .aggregate() - for aggregations
  • .mapReduce() - for mapReduce
  • .batch() - to create sequential bulk writes
  • .parallel() - to create parallel bulk writes

The API is somewhat subject to change so they won't be documented thoroughly. If what you "expect" to work does not work, please let us know so we can figure out how to improve the API. If you're in doubt, look at the code.

Options

Most options are available as chainable methods.

collection.insert({
  name: 'username'
}).w('majority'))

Update operators are also methods with the $ prefix as well as without if there are no conflicts:

collection.find({
  name: 'username'
}).set('name', 'new_username').w('majority')

// there's no .push() because that's a streams2 API method name
collection.find({
  name: 'username'
}).$push('names', 'new_username')

Promises

All methods have .then() and .catch(), allowing them to be yield or awaited.

collection.find().then(function (docs) {

}, function (err) {

})

co(function* () {
  var docs = yield collection.find({
    name: 'jon'
  })
}).catch(function (err) {
  console.error(err.stack)
  process.exit(1)
})

Streams

The .find() method, when not used with any .update() or .remove() commands, returns a stream.

collection.find().pipe(JSONStream.stringify()).pipe(process.stdout)

Callbacks

Callbacks are only supported using the .exec() or .end() commands.

collection.find().end(function (err, doc) {

})

Transforms

You may chain transforms, equivalent to [].map():

collection.find().map(function (x) {
  x.transform1 = true
  return x
}).map(function (x) {
  x.transform2 = true
  return x
})

Options

You may set options yourself using the .setOption() or .setOptions() methods:

collection.find().setOptions({})
collection.find().setOption('key', 'value')

Examples

Insert with write concern:

collection.insert([{
  name: 'jon'
}, {
  name: 'mary'
}]).w('majority')

Find both of the above documents and pipe:

var stringify = require('JSONStream').stringify

collection
.find()
// create $or: [], though a `name: {$in: []}` would probably be better here
.or('name', 'jon')
.or('name', 'mary')
.readPreference('secondaryPreferred')
.pipe(stringify)
.pipe(process.stdout)

Equivalent of .findAndModify() and returning the new object:

collection
.find('name', 'jon')
.set('name', 'Jonathan')
.new()

Do a multi update, which is by default unless .new() or .remove() are chained or .updateOne() is used`:

collection
.find('species', 'human')
.set('ancestor', 'neanderthal')
.w('majority')

Do an aggregation:

collection.aggregate()
.match({
  type: 'human'
})
.group({
  _id: '$value',
  count: {
    $sum: 1
  }
})
.limit(10)

Do a mapReduce:

collection.mapReduce()
.map(function () {
  emit(this.name, this.score)
})
.reduce(function (key, values) {
  return Array.sum(values)
})
.then(function (result) {
  console.log(result)
})

By default, the out is { inline: 1 }, the methods below are available.

  • .out()
  • .sort()
  • .query()
  • .limit()
  • .scope()
collection.mapReduce()
.map(function () {
  emit(this.name, this.score)
})
.reduce(function (key, values) {
  return Array.sum(values)
})
.out({
  merge: 'collectionName'
})
.then(function (col) {
  col.find().then(function (docs) {
    console.log(docs)
  })
})

Paginate:

function query(options) {
  options = options || {}
  collection.find()
  .skip(options.skip || 0)
  .limit(options.limit || 25)
}