Skip to content
This repository has been archived by the owner before Nov 9, 2022. It is now read-only.


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


Build Status npm version Coverage Status Dependency Status bitHound Overall Score Join the chat at GitHub stars

MarsDB is a lightweight client-side database. It's based on a Meteor's minimongo matching/modifying implementation. It's carefully written on ES6, have a Promise based interface and may be backed with any storage implementation (see plugins). It's also supports observable cursors.

MarsDB supports any kind of find/update/remove operations that Meteor's minimongo does. So, go to the Meteor docs for supported query/modifier operations.

You can use it in any JS environment (Browser, Electron, NW.js, Node.js).


  • Promise based API
  • Carefully written on ES6
  • Very very flexible – just take a look to the plugins section
  • Supports many of MongoDB query/modify operations – thanks to a Meteor's minimongo
  • Flexible pipeline – map, reduce, custom sorting function, filtering. All with a sexy JS interface (no ugly mongo's aggregation language)
  • Persistence API – all collections can be stored (and restored) with any kind of storage (in-memory, LocalStorage, LevelUP, etc)
  • Observable queries - live queries just like in Meteor, but with simplier interface
  • Reactive joins – out of the box



Meteor compatible client/server

Sometimes you can't use Meteor infrastructure. Maybe you need to build a custom client. Maybe you need to build a custom server with express and other modules. In meteor it can be done with a ton of hack. But the only reason why it's so ugly to do a simple things is because Meteor forces you to use their infrastructure. I'm trying to solve this issue with DDP client/server modules, based on MarsDB.


Using within non-ES6 environment

The ./dist folder contains already compiled to a ES5 code, but some polyfills needed. For using in a browser you must to include marsdb.polyfills.js before marsdb.min.js. In node.js you need to require('marsdb/polyfills'). It sets in a window/global: Promise, Set and Symbol.

Create a collection

import Collection from 'marsdb';
import LocalForageManager from 'marsdb-localforage';

// Default storage is in-memory
// Setup different storage managers
// (all documents will be save in a browser cache)

// Create collection wit new default storage
const users = new Collection('users');

Create an in-memory collection

import Collection from 'marsdb';
import LocalStorageManager from 'marsdb-localstorage';

// Set some defaults and create collection
const users = new Collection('users');

// But it may be useful to create in-memory
// collection without defined defaults
// (for example to save some session state)
const session = new Collection('session', {inMemory: true});

Find documents

const posts = new Collection('posts');
posts.find({author: 'Bob'})
  .project({author: 1})
  .then(docs => {
    // do something with docs

Find with pipeline (map, reduce, filter)

An order of pipeline methods invokation is important. Next pipeline operation gives as argument a result of a previous operation.

const posts = new Collection('posts');

// Get number of all comments in the DB
  .sortFunc((a, b) => a - b + 10)
  .filter(doc => Matsh.sqrt(doc.comment.length) > 1.5)
  .map(doc => doc.comments.length)
  .reduce((acum, val) => acum + val)
  .then(result => {
    // result is a number of all comments
    // in all found posts

// Result is `undefined` because posts
// is not exists and additional processing
// is not ran (thanks to `.ifNotEmpty()`)
posts.find({author: 'not_existing_name'})
  .aggregate(docs => docs[0])
  .aggregate(user =>

Find with observing changes

Observable cursor returned by a find and findOne methods of a collection. Updates of the cursor is batched and debounced (default batch size is 20 and debounce time is 1000 / 15 ms). You can change the paramters by batchSize and debounce methods of an observable cursor (methods is chained).

const posts = new Collection('posts');
const stopper = posts.find({tags: {$in: ['marsdb', 'is', 'awesome']}})
  .observe(docs => {
    // invoked on every result change
    // (on initial result too)
    stopper.stop(); // stops observing
  }).then(docs => {
    // invoked once on initial result
    // (after `observer` callback)

Find with joins

const users = new Collection('users');
const posts = new Collection('posts');
  .join(doc => {
    // Return a Promise for waiting of the result.
    return users.findOne(doc.authorId).then(user => {
      doc.authorObj = user;
      // any return is ignored
  .join(doc => {
    // For reactive join you must invoke `observe` instead `then`
    // That's it!
    return users.findOne(doc.authorId).observe(user => {
      doc.authorObj = user;
  .join((doc, updated) => {
    // Also any other “join” mutations supported
    doc.another = _cached_data_by_post[doc._id];

    // Manually update a joined parameter and propagate
    // update event from current cursor to a root
    // (`observe` callback invoked)
    setTimeout(() => {
      doc.another = 'some another user';
    }, 10);
  // Or just pass join spec object for fast joining
  // (only one `find` will be produced for all posts)
  .join({ authorId: users }) // posts[i].authorId will be user object
  .observe((posts) => {
    // do something with posts with authors
    // invoked any time when posts changed
    // (and when observed joins changed too)


const posts = new Collection('posts');
posts.insert({text: 'MarsDB is awesome'}).then(docId => {
  // Invoked after persisting document
  {text: 'MarsDB'},
  {text: 'is'},
  {text: 'awesome'}
).then(docsIds => {
  // invoked when all documents inserted


const posts = new Collection('posts');
  {authorId: {$in: [1, 2, 3]}},
  {$set: {text: 'noop'}}
).then(result => {
  console.log(result.modified) // count of modified docs
  console.log(result.updated) // array of updated docs
  console.log(result.original) // array of original docs

// Upsert (insert when nothing found)
  {authorId: "123"},
  {$set: {text: 'noop'}},
  {upsert: true}
).then(result => {
  // { authorId: "123", text: 'noop', _id: '...' }


const posts = new Collection('posts');
posts.remove({authorId: {$in: [1,2,3]}})
  .then(removedDocs => {
    // do something with removed documents array


  • Indexes support for some kind of simple requests {a: '^b'}, {a: {$lt: 9}}
  • Documentation


I'm waiting for your pull requests and issues. Don't forget to execute gulp lint before requesting. Accepted only requests without errors.


See License


MarsDB is a Promise based lightweight database with MongoDB query syntax, written on ES6







No packages published