MarsDB
MarsDB is a lightweight client-side database.
It's based on a Meteor’s minimongo
matching/modifying implementation. It's carefully written on ES6
, usess modular lodash
, have a Promise
based interface and may be backed with any storage implementation (LevelUP, LocalStorage, IndexedDB, etc). For now implemented only LocalStorage and LocalForage storage managers. 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).
Features
- Promise based API
- Carefully written on ES6
- 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
Examples
Using with Angular 1.x
Include marsdb.angular.js
after marsdb.min.js
and angular.js
in your <head>
. Then add a MarsDB
dependency in your module. That's it. Now you can use $collection
factory. For example:
angular.module(‘app’, [‘MarsDB’])
.controller(function($scope, $collection) {
const posts = $collection(‘posts’);
posts.find({authorId: 123}).observe((docs) => {
$scope.posts = docs;
}, $scope).then(() => {
$scope.loaded = true;
});
});
You also can use MarsDB within browserify environment. Just require(‘marsdb/dist/angular’)
and MarsDB module will be added to the angular. Angular must be defined in a window
or must be available as a module require(‘angular’)
.
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 LocalStorageManager from 'marsdb/lib/LocalStorageManager';
Collection.defaultStorageManager(LocalStorageManager);
Collection.defaultIdGenerator(() => {
return {
value: Math.random(),
seed: 0,
};
});
const users = new Collection(‘users’);
Find a documents
const posts = new Collection(‘posts’);
posts.find({author: ‘Bob’})
.sort([‘createdAt’])
.then(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’);
posts.find()
.limit(10)
.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 => {
});
posts.find({author: 'not_existing_name'})
.aggregate(docs => docs[0])
.ifNotEmpty()
.aggregate(user => user.name)
Find with observing changes
Observable cursor returned only by a find
method 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 => {
stopper.stop();
}).then(docs => {
});
Find with joins
const users = new Collection(‘users’);
const posts = new Collection(‘posts’);
posts.find()
.join(doc => {
return users.findOne(doc.authorId).then(user => {
doc.authorObj = user;
});
})
.join(doc => {
return users.findOne(doc.authorId).observe(user => {
doc.authorObj = user;
});
})
.join(doc => {
doc.another = _cached_data_by_post[doc._id];
})
.observe((posts) => {
})
Inserting
const posts = new Collection(‘posts’);
posts.insert({text: ‘MarsDB is awesome’}).then(docId => {
})
posts.insertAll(
{text: ‘MarsDB’},
{text: ‘is’},
{text: ‘awesome’}
).then(docsIds => {
});
Updating
const posts = new Collection(‘posts’);
posts.update(
{authorId: {$in: [1, 2, 3]}},
{$set: {text: ‘noop’}}
).then(result => {
console.log(result.modified)
console.log(result.updated)
console.log(result.original)
});
Removing
const posts = new Collection(‘posts’);
posts.remove({authorId: {$in: [1,2,3]}})
.then(removedDocs => {
});
Roadmap
- Keep track of multiple remove/update documents in selector (allow only if opations.multi passed)
- Upsert updating
- Indexes support for some kind of simple requests {a: '^b'}, {a: {$lt: 9}}
- Some set of backends
- Documentation
Contributing
I’m waiting for your pull requests and issues.
Don’t forget to execute gulp lint
before requesting. Accepted only requests without errors.
License
See License