Git Product home page Git Product logo

mongorito's Introduction




Lightweight and flexible MongoDB ODM for Node.js apps based on Redux.

Build Status Coverage Status

Features

Flexible

Mongorito is based on Redux, which opens the doors for customizing literally everything - from model's state (reducers) to the behavior of core methods, like set(), save() or find().

Each model instance has a separate Redux store, which ensures isolation between other models and easy extensibility.

No schemas

If MongoDB doesn't enforce schemas, why would Mongorito do? Enjoy the schema-free data management with Mongorito the same way you do in mongo console.

Lightweight

Mongorito is betting on 3rd-party plugins to deliver extra functionality to developers. Mongorito ships with a barebones model with basic get/set, save/remove and querying functionality and let's you be in control of what's included and what's not.

Mongorito is basically a tiny Redux-based application, which uses the official MongoDB driver and mquery for querying. Not that amount of lines are relevant when measuring complexity, but each file (module) is less than 300 lines. Check out the source code and see for yourself!

Quick overview

const {Database, Model} = require('mongorito');

const db = new Database('localhost/blog');
await db.connect();

class Post extends Model {}

db.register(Post);

const post = new Post({
	title: 'Steve Angello rocks',
	author: {
		name: 'Emma'
	}
});

await post.save();

post.set('author.name', 'Rick');
await post.save();

await db.disconnect();

Note: await won't work at top level, it's used to reduce the complexity of an example.

Installation

$ npm install --save mongorito

Contents

Connection

Mongorito exports several own classes, as well as a few properties from the MongoDB driver:

const {
	Database,
	Model,
	Timestamp,
	ObjectId,
	MinKey,
	MaxKey,
	DBRef,
	Long
} = require('mongorito');

Database and Model are Mongorito's own exports, all the other ones are exported straight from mongodb package for convenience. Normally, you'd need only Database, Model and ObjectId.

To connect, initialize a Database, which accepts a MongoDB connection string and an optional configuration which will be passed to mongodb's connect function.

To connect and disconnect use connect()/disconnect() methods. Both returns a Promise.

For convenience, await will be used in all examples below, even though it doesn't work at top level.

const {Database, Model} = require('mongorito');

const db = new Database('localhost/blog', {
	reconnectTries: 5
});

await db.connect();
await db.disconnect();

You don't have to wait until connection establishes to perform operations. Mongorito automatically executes pending operations once connection is up.

Models

Creating a model

Model is the connection between your data and a database. Each model represents a single collection. Model is a simple class, which doesn't even need to have any properties or methods.

class Post extends Model {}

For Post model to work and be aware of the database it's connected to, make sure to register it in the database we created earlier.

db.register(Post);

That's it, the Post model is good to go!

Working with fields

To create a new document, create an instance of Post model.

const post = new Post();

Model's constructor also accepts an object of fields to instantiate the document with:

const post = new Post({
	title: 'Great post',
	author: {
		name: 'Sarah'
	}
});

Note, documents can contain nested fields and even models, just like in MongoDB.

To get one or all fields from the post document, use a get() method.

const title = post.get('title');
//=> "Great post"

const author = post.get('author.name');
//=> "Sarah"

const data = post.get();
//=>
//  {
//    title: "Great post"
//    author: {
//      name: "Sarah"
//    }
//  }

Similarly, use set() to update fields:

// update fields one by one
post.set('title', 'Amazing post');
post.set('author.name', 'Monica');

// or all at once
post.set({
	title: 'Amazing post',
	author: {
		name: 'Monica'
	}
});

To remove a field, use unset():

// unset single fields
post.unset('title');
post.unset('author.name');

// or multiple fields at once
post.unset(['title', 'author.name']);

Saving or removing documents

To create or update documents, simply call save(). Even though Mongorito differentiates these two operations internally, you don't have to care about that! Mongorito also infers the collection name from the model, so the instances of the model Post will be saved to posts collection.

await post.save();

When a document is saved, an _id field is automatically added.

post.get('_id');
//=> ObjectId("5905cb6b543c3a50e03e810d")

To remove a document, use remove().

await post.remove();

To remove multiple documents, use remove() on the model itself with a query as an argument.

await Post.remove({good: false});

Incrementing fields

Mongorito also provides a handy increment() method to increment or decrement numerical fields:

const post = new Post({
	views: 0
});

await post.increment('views');

post.get('views');
//=> 1

You can also supply a value to increment a field by a specific amount.

await post.increment('views', 2);

post.get('views');
//=> 3

Multiple fields can be incremented at once, too.

const post = new Post({
	views: 10,
	comments: 10
});

await post.increment({
	views: 2,
	comments: 5
});

post.get('views');
//=> 12

post.get('comments');
//=> 15

Embedding other models

Just like MongoDB, Mongorito allows to effortlessly embed other models. They're transparently converted between JSON and Mongorito models.

To embed models, use embeds() method on the model itself to help Mongorito with the model serialization when saving/reading from the database. embeds() method accepts a field name, where the embedded document (or array of documents) resides.

Here's the quick overview on how it works. Note, that model registering via register() is skipped in the following example.

class Post extends Model {}
class Author extends Model {}
class Comment extends Model {}

Post.embeds('author', Author);
Post.embeds('comments', Comment);

const post = new Post({
	title: 'Great post',
	author: new Author({name: 'Steve'}),
	comments: [new Comment({body: 'Interesting!'})]
});

await post.save();

The above post will be saved to the database as:

{
	"title": "Great post",
	"author": {
		"name": "Steve"
	},
	"comments": [
		{
			"body": "Interesting!"
		}
	]
}

You can also just pass objects instead of model instances and Mongorito will take care of that too.

const post = new Post({
	title: 'Great post',
	author: {
		name: 'Steve'
	},
	comments: [{
		body: 'Interesting!'
	}]
});

When that document will be retrieved from the database next time, all embedded documents will be wrapped with their corresponding models.

const post = await Post.findOne();

const author = post.get('author');
//=> Author { name: "Steve" }

author.get('name');
//=> "Steve"

Configuration

Using a different collection name

In case you need to store documents in a custom collection, you can override the default one using collection() method.

class Post extends Model {
	collection() {
		return 'awesome_posts';
	}
}

Queries

Mongorito uses mquery to provide a simple and comfortable API for querying. It inherits all the methods from mquery with a few exceptions, which will be documented below. For documentation, please check out mquery's API - https://github.com/aheckmann/mquery.

Here's a quick overview of how querying works in Mongorito. All documents returned from queries are automatically wrapped into their models.

// find all posts
await Post.find();

// find all amazing posts
await Post.find({amazing: true});
await Post.where('amazing', true).find();

// find 5 recent posts
await Post
	.limit(5)
	.sort('created_at', 'desc')
	.find();

// find one post
await Post.findOne({incredible: 'yes'});

// count posts
await Post.count({super: false});

Plugins

Using plugins

To use a 3rd-party plugin, all you have to do is to call use() method.

const timestamps = require('mongorito-timestamps');

db.use(timestamps());

This will apply mongorito-timestamps to models registered after that.

If you want to apply the plugin to a specific model only, call it on the model itself.

Post.use(timestamps());

Writing plugins

A plugin is simply a function that accepts a model. A familiarity with Redux and its concepts will help you tremendously with writing plugins.

const myPlugin = model => {
	// do anything with model (Post, in this case)
};

Post.use(myPlugin);

Feel free to assign new methods to the model or instances, add new middleware, modify the model's state and anything that comes to your mind.

Extending model with new methods

Here's an example of adding a class method and an instance method to a Post model.

const extendPost = Post => {
	Post.findRecent = function () {
		return this
			.limit(5)
			.sort('created_at', 'desc')
			.find();
	};

	Post.prototype.makeAmazing = function () {
		this.set('amazing', true);
	};
};

Post.use(extendPost);

const post = new Post();
post.makeAmazing();
post.get('amazing');
//=> true

const posts = await Post.findRecent();
//=> [Post, Post, Post]

Modifying model's state

If you plugin needs to have its own state, you can modify the model's reducer using modifyReducer() method. It accepts a function, which receives the existing reducer shape as an argument and should return a new object with added reducers.

const customReducer = (state = null, action) => {
	// reducer code...
};

const extendReducer = model => {
	model.modifyReducer(reducer => {
		return {
			...reducer,
			customState: customReducer
		}
	});
};

Changing behavior using middleware

Middleware can be used to change or modify the behavior of model's operations. You can interact with everything, from get/set operations to queries.

To add plugin's custom middleware to the default middleware stack, return it from the plugin function.

const myPlugin = () => {
	return store => next => action => {
		// middleware code...
	};
};

Obviously, to detect what kind of action is being handled, you need to be aware of Mongorito's action types.

const {ActionTypes} = require('mongorito');

const myPlugin = () => {
	return store => next => action => {
		if (action.type === ActionTypes.SET) {
			// alter set() behavior
		}

		return next(action);
	};
};

Again, the middleware is identical to the middleware you're used to when writing apps with Redux. There are only 2 new properties added to the store:

  • model - instance of the model (document) the middleware is currently running in. If middleware is running at the model level (without instantiated model), it will be undefined.
  • modelClass - model class (Post, for example).

Here's an example on how to access all props of the store:

const myPlugin = () => {
	return ({getState, dispatch, model, modelClass}) => next => action => {
		// `getState()` and `dispatch()` are from Redux itself
		// `model` is `post`
		// `modelClass` is `Post`

		return next(action);
	};
};

Post.use(myPlugin);

const post = new Post();
await post.save();

For examples on how to write middleware, check out Mongorito's native ones - https://github.com/vadimdemedes/mongorito/tree/master/lib/middleware.

Migrating from legacy version

Connection

Before:

const mongorito = require('mongorito');

mongorito.connect('localhost/blog');

After:

const {Database} = require('mongorito');

const db = new Database('localhost/blog');
await db.connect();

License

MIT © Vadim Demedes

mongorito's People

Contributors

adieuadieu avatar brianvanburken avatar edencoder avatar greenkeeperio-bot avatar hbbbs avatar mdmellis avatar mrusme avatar olistic avatar paullryan avatar saikirandaripelli avatar sirbyalive avatar zaaack avatar zizaco avatar zordak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mongorito's Issues

Single Collection Inheritance

I need to store several models in the same collection, and be able to discriminate between objects, based on the specific model that I'm querying. Like so:

var Account = Mongorito.Model.extend({
   collection: 'accounts',
   configure: function () {
      this.before('save', 'validate');
   },
   validate: function * (next) {
      // some basic validations for all models inheriting from Account
      yield next;
   }
});

var User = Account.extend({
   configure: function () {
      this.before('save', 'validateEmailExists');
   },
   validateEmailExists: function * (next) {
      // validate that email exists
      yield next;
   }
});

Validations, like validateEmailExists on the User model, should be fired after the Account validations pass.

And when I call Account.find(), I will expect to see all models stored in the accounts collection for a given query, regardless of the model that was instantiated and saved to create this record. However, if I call User.find(), I should only return records that were created by the User model.

Mongoose handles this by using a discriminator function, which is mostly undocumented and I think, rough to use. Is there a simple way to handle this use case in Mongorito?

Fail on install

When I clone repo and try install dependences use npm i I got error:

npm ERR! Darwin 14.3.0
npm ERR! argv "/Users/zhigalov/.nvm/versions/node/v0.12.0/bin/node" "/Users/zhigalov/.nvm/versions/node/v0.12.0/bin/npm" "i"
npm ERR! node v0.12.0
npm ERR! npm  v2.5.1
npm ERR! code EPEERINVALID

npm ERR! peerinvalid The package mongodb does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer [email protected] wants mongodb@~1.4

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/zhigalov/backend/mongorito/npm-debug.log

When I update node version I got error:

npm ERR! Darwin 14.3.0
npm ERR! argv "/Users/zhigalov/.nvm/versions/node/v0.12.6/bin/node" "/Users/zhigalov/.nvm/versions/node/v0.12.6/bin/npm" "i"
npm ERR! node v0.12.6
npm ERR! npm  v2.11.2
npm ERR! path /Users/zhigalov/backend/mongorito/node_modules/mocha/node_modules/jade/bin/jade
npm ERR! code ENOENT
npm ERR! errno -2

npm ERR! enoent ENOENT, chmod '/Users/zhigalov/backend/mongorito/node_modules/mocha/node_modules/jade/bin/jade'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.

I try in node-v0.12.6 and iojs-v2.3.3.

What I doing wrong?

Unable to find by id?

I'm trying to find by an ObjectId, but it looks like it's getting converted to a string and thus not returning any documents from the DB.

Simple repo:

Mongorito = require 'mongorito'
ObjectId = require('mongolian').ObjectId

Mongorito.connect ['mongo://...@.../...']

class Doc

Doc = Mongorito.bake Doc

Doc.find( _id: '...', (err, doc) -> console.log doc.length ) // returns 0
Doc.find( _id: new ObjectId('...'), (err, doc) -> console.log doc.length ) // returns 0
Doc.find( title: 'foo', (err,doc) -> console.log doc.length ) // returns 1 (success)

JSON Object of Current Model State?

How would I access the current model state as a JSON object? (I'm using Joi to handle validation). Basically, I need something like this:

* validate (next) {
   let schema = {
      title: joi.string()
   };

   let currentState = {
      title: this.get('title')
   };

   joi.validate(schema, object, {}, function (err) {
      if (err) throw err;
      yield next;
   });
}

Does this look correct?

Changed attributes current implementation leading to false negatives

On the assumption that the changed object of a model would be primary used when asking for undefined values, the current implementation of the set method -which assigns the new value to the changed object under the corresponding key- can lead to false negatives.

Suppose we have a User model with a middleware that makes the following check:

if (!this.changed.admin) {
   ...
}

If the admin attribute of that model has changed from true to false, that check will indicate that the value didn't change, when it actually did.

TypeError: Cannot read property 'is' of undefined

I'm running the latest version (0.6.13 ) with iojs 1.5.1 using --es_staging --use_strict.

Here is the stack trace:

|TypeError: Cannot read property 'is' of undefined
|     at /usr/src/app/node_modules/mongorito/node_modules/is_js/is.js:29:26
|     at root (/usr/src/app/node_modules/mongorito/node_modules/is_js/is.js:18:26)
|     at Object.<anonymous> (/usr/src/app/node_modules/mongorito/node_modules/is_js/is.js:23:2)
|     at Module._compile (module.js:444:26)
|     at Object.Module._extensions..js (module.js:462:10)
|     at Module.load (module.js:339:32)
|     at Function.Module._load (module.js:294:12)
|     at Module.require (module.js:349:17)
|     at require (module.js:368:17)
|     at Object.<anonymous> (/usr/src/app/node_modules/mongorito/build/mongorito.js:22:10)
|     at Module._compile (module.js:444:26)
|     at Object.Module._extensions..js (module.js:462:10)
|     at Module.load (module.js:339:32)
|     at Function.Module._load (module.js:294:12)
|     at Module.require (module.js:349:17)
|     at require (module.js:368:17)

Remove attributes

How can i do to remove attribute ?
i create temporary attributes like token to recover password. But after used this attribute i want to remove from my Document.
I see nothing in set method which remove attribute if nothing is passed or null value...

Run asynchronously

Hello,

if I want to run the following code:

var post = yield Posts.where("_id", "someid").find();

post.title = "New title";

post.save(); // without yield

var otherPost = yield Posts.where("_id", "someotherid").find();

will it work? Since I don't need to wait for the result of post.save(), may I run it asynchronously?

Query operator OR

I need to make a request like { $or: [{ a:1 }, { b:2 }] }

If I use method

MyModel.or([{ a:1 }, { b:2 }]).find()

than I get a request {"[object Object],[object Object]":{}} because in here key-value pair is required.

If I use

MyModel.find({ $or: { a:1 },  { b:2 }})

then my request transforms to {"$or":{"$elemMatch":[{"a":1},{"b":2}]} because of.

So the question is, what is a correct way to make a request like { $or: [{ a:1 }, { b:2 }] }?

Query problem ($elemMatch misuse)

Hello,
I have some problems with the query creation and i think the problems are related to the use of $elemMatch (here src/query.js).

My code is basically like this:

let query = {
  "date": {
      "$gte": "2015-05-05T00:00:00.000Z", // Not the string, the Date object
      "$lte": "2015-05-06T23:59:59.999Z" // Not the string, the Date object
    }
};

let result = yield* query.find( query );

But if i enable the DEBUG i see the generated query is:

monk:queries posts find {"date":{"$elemMatch":{"$gte":"2015-05-05T00:00:00.000Z","$lte":"2015-05-06T23:59:59.999Z"}}}

And i get no results while using the mongo console my query works.

The problem is related to the fact that $elemMatch works on array fields (see here)

The $elemMatch operator matches documents that contain an array field with at least one element that matches all the specified query criteria.

Add use method with co-style generator and return a Promise.

I would suggest adding a Mongorito.use(connection, generatorFn) method. Where connection can be an established MongoDB client connection/pool, or a mongodb style connection string. and the generator function receives the Mongorito instance to use, where the connect/disconnect happen in the wrapper... the generatorFn essentially called like co@4 and returning a Promise.

Mongorito.use(cnstr, function *(db) {
  //do stuff with db
}).then(function (){
  //it's all good
}).catch(function(err){
  //oh noes!!!
});

This would allow for someone writing a db layer to use Mongorito with co-style interaction in a generator, but have a final return that can be the promise... allowing for thenable chains outside said method. :-)

how to set collection with "class" keyword

This is not an issue, I just need a little help here.

In the "Getting Started" page, it shows a way to define a Post with "class" keyword:
class Post extends Model {}

Then, how should I set the collection?
I tried something like this:

class Post extends Model {
constructor() {
super();
this.collection = 'posts';
}

but doesn't work. I don't want to use:
var Post = Model.extend({collection: 'posts'});
I wanna use the "class" keyword.

Then how should I set the collection? thanks.

CircleCI build error

Hi, I've run the test suite from my local machine and everything looks like it's passing. However, the badge for CirculeCI is showing a failure.

Sanitizing input via this.attributes

I just tried to assign this.attributes to a sanitized object (in a pre-save validation function), and get an error:

Cannot read property 'created_at' of undefined

Which, I assume, means I overrode something that I should've left alone. Is there a clean way to handle this at the model level, or should I do sanitization before it hits the model?

Return deep copy in .get()

Return deep copy, instead of reference (in case of objects) when using .get() to prevent accidental modification of model's attributes.

Mongorito.close() is async, but not yield friendly.

When reconnect mongo After Mongorito.close(), and do some save/query, it will throw an err that "connection is closed by Application."

which is casued by Mongorito.close() is async, but not yield friendly.

Here is an example:

co(function(){
    Mongorito.connect(url);
    //get data from mongo
    Mongorito.close();   //<- it's async, but not yield friendly.
}).then(function(doc){
    // ---->connection is still open.
    Mongorito.connect(url);
    // ---->connection is just closed.
    //update doc and save to mongo. <- Get an err caused by "Connection is closed"
    Mongorito.close();
})

Then how could I do Mongorito.close() with yield? thanks.

collection property es6

Hi I am trying to set the collection name by defining the "collection" property on the class. My code looks like this:

class Abc extends Model {
collection: 'collectionName';
}

collectionName is being ignored

I don't know why?

That is all of code

// test.js   
var Mongorito = require('mongorito')
console.log(Mongorito)

I got this error when i perform node --harmony test.js

/Users/xiaofeng/working/node/52dachu/node_modules/mongorito/node_modules/monk/node_modules/mongoskin/lib/utils.js:33
  var skinClassName = 'Skin' + NativeClass.name;
                                          ^
TypeError: Cannot read property 'name' of undefined
    at makeSkinClass (/Users/xiaofeng/working/node/52dachu/node_modules/mongorito/node_modules/monk/node_modules/mongoskin/lib/utils.js:33:43)
    at Object.<anonymous> (/Users/xiaofeng/working/node/52dachu/node_modules/mongorito/node_modules/monk/node_modules/mongoskin/lib/admin.js:18:37)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/xiaofeng/working/node/52dachu/node_modules/mongorito/node_modules/monk/node_modules/mongoskin/lib/db.js:20:17)
    at Module._compile (module.js:460:26)

Cannot perform text search in documents.

First and foremost, thank you for such great work. I really like your project and the idea of hooks is awesome. Please take a minute to review my issues, I tried the guides and there's no example for this situation.

I currently have a collection with a text index. Using the mongo console, I am able to search my documents like so:

db.cities.find({ '$text': { '$search': 'San Francisco' } }

I have tried this using Mongorito:
let cities = yield City.where({'$text': {$search: 'San Francisco'}}).find();

and also the find version of it:
let cities = yield City.find({'$text': {$search: 'San Francisco'}})

This search never returns any results though. I suspect is due to the fact that it is searching in the existing model properties, and $text is a reserved mongo property. How could I achieve this?

Also, another common operation when dealing with text search is to sort on the $textScore meta property. For instance:

db.cities.find({ '$text': { '$search': 'San Francisco' } }, {'score': {'$meta': 'textScore'}}) .sort({'score': {'$meta': 'textScore'}})

This code is finding the city with the text San Francisco in the indexed text property, then projecting the textScore meta property, then sorting using that score. How would you be able to achieve this using Mongorito?

Thank you.

Equivalent of $push ?

Hi,

I am quite new to node AND mongo, please be patient :)

I am currently in the process of rewriting a webapp's persistence using mongorito. So far I like it quite a lot.

But I need to do things like add comments to an issue, or add followers. These are represented in my schema as arrays of ids or arrays of objects inside the main document.

It used to be implemented using the native mongo $push keywords, like this:

db.discussion.update(
    { 'discussion_id': discussion_id },
    { '$push': { 'comments': {
        'posted': datetime.utcnow(),
        'author': author_info,
        'text': comment_text } } } );

Using Mongorito, I could not find an equivalent to this construct. The workaround is to load the whole parent (discussion in this example), add the comment or follower, and finally save the whole object again. This is not optimal. 2 DB hits instead of one, and potentially loading a big object just to add a single id in an array.

What would you recommend instead ? Is there support for this kind of operations built into Mongorito ?

create method seems to be misbehaving without cache :)

line 320..

    save: (callback) ->
        that = @
        fields = do @fields
        
        notFields = ['constructor', 'save', 'collection', 'create', 'fields', 'update', 'remove', 'models']
        keys = []
        for field of @
            keys.push field if -1 is notFields.indexOf field
        
        async.filter keys, (key, nextKey) ->
            if that["validate#{ key.camelize() }"]
                that["validate#{ key.camelize() }"] (valid) ->
                    nextKey not valid
            else
                nextKey false
        , (results) ->
            return callback yes, results if results.length > 0
            
            Cache.delByTag that.collection, -> ##stuff goes bad at this line
            if fields._id
                that.update callback, yes
            else
                that.create callback, yes

seems to be not working without cache..

DEBUG: TypeError: Cannot call method 'delByTag' of undefined
    at /home/blogy/node_modules/mongorito/lib/mongorito.js:432:20
    at /home/blogy/node_modules/mongorito/node_modules/async/lib/async.js:245:13
    at /home/blogy/node_modules/mongorito/node_modules/async/lib/async.js:105:25
    at /home/blogy/node_modules/mongorito/node_modules/async/lib/async.js:242:17
    at /home/blogy/node_modules/mongorito/lib/mongorito.js:428:16
    at /home/blogy/node_modules/mongorito/node_modules/async/lib/async.js:238:13
    at /home/blogy/node_modules/mongorito/node_modules/async/lib/async.js:97:13
    at Array.forEach (native)
    at /home/blogy/node_modules/mongorito/node_modules/async/lib/async.js:26:24
    at /home/blogy/node_modules/mongorito/node_modules/async/lib/async.js:96:9

commenting out the caching line .. seems to work!

Upgrade monk to 1.0.0

Would you mind upgrading monk to 1.0.0?

It appears that it would fix this annoying little thing when using iojs:

js-bson: Failed to load c++ bson extension, using pure JS version

Models for subdocuments.

This project looks like it has almost everything I need except for th ability to have sub document models. Or am I missing something?

Error occured while fetch all records

on start I get this error:

[Error: Module did not self-register.]
js-bson: Failed to load c++ bson extension, using pure JS version

and when I try to yield SomeModel.all();
this error throws:

TypeError: Cannot read property 'find' of undefined
      at Query.find (/Users/artem/Projects/elastic/metagen/node_modules/mongorito/lib/query.js:127:37)
      at GeneratorFunctionPrototype.next (native)

My model looks like

var Mongorito = require('mongorito');
var Model = Mongorito.Model;
Mongorito.connect('mongodb://localhost:27017/mydb');

var Api = Model.extend({
    collection: function () {
        return 'apis';
    }
});

module.exports = Api;

I'm using Koajs and iojs

Getting Started tutorial wrong

Code you provide at getting started generates error "SyntaxError: Unexpected identifier"
at yield statements.
Your code needs to be wrapped in a "co" generator function before you can execute it.

var co = require('co');
co(function *(){
  var posts;

  posts = yield Post.find(); // same as .all()

  // match documents with title = "Great title"
  posts = yield Post.find({ title: 'Great title' });
  posts = yield Post.where('title', 'Great title').find();
  posts = yield Post.where('title').equals('Great title').find();
}

Expose ObjectID from mongoskin

Is there any chance to expose MongoDB objects from mongorito?

In utils you get them from mongoskin: https://github.com/vdemedes/mongorito/blob/master/lib/util.js#L5 but in my code it will be look like:

var ObjectID = require('mongorito/node_modules/monk/node_modules/mongoskin').ObjectID;

This is far beyond good path for require - can it be like this (ideal):

var ObjectID = require('mongorito').ObjectID;

P.s. Thanks for awesome module 🐶

Atomic increment

I need increment field value use mongo $inc

Should there be the $inc in the mongorito?
What do you think about this:

var post = yield Post.findById(postId);
yield post.inc({comments: 1});

use:

* inc(increment) {
    var collection = this._collection;
    var id = this.attributes._id;

    var options = {
        $set: {updated_at: new Date()},
        $inc: increment
    }

    yield collection.updateById(id, options);

    return this;
};

Mongodb 3.x query format support

Does Mongorito support all query expression as of MongoDB 3.x native driver ?
e.g. db..aggregate
If yes can we update it to doc ?

save returning without actually saving the document

Firstly, I am not using co or any other library like that.


function* p() {
    Mongorito.connect('ipaddress/blog');
    var post = new Post({
        title: 'Node.js with --harmony rocks!',
        body: 'Long post body',
        author: {
            name: 'John Doe'
        }
    });
    yield post.save();
}
var x = p();
console.log(x.next());

The above code should have worked IMO because p() will not yield until the document has been saved.
However, post.save() yields immediately with the output { value: {}, done: false }.

The following code does save the document but yields a function


yield* post.create(); //replaced yield.post.save()

Output:


{ value: [Function], done: false }

I can see that the new document has been saved in the MongoDB.
Can some one please help?

Support for upsert?

Does mongorito support upsert operations i.e. calling collection.update with query, update, and options specifying {upsert: true} ?

Looking at the docs and code, I couldn't see a way to do this unless I'm missing something?

js

"Nothing special, you will just have to use dirtier syntax, but that's ok." - no one writes their js like that haha dont be dumb

Catching errors

Hello,

I have the following code:

yield User.index('email', { unique: true });


var salt = yield bcrypt.genSalt(10);

var user = new User({
  email: this.request.body.email,
  password: yield bcrypt.hash(this.request.body.password, salt),
  salt: salt
});

try {
  yield user.save();
} catch (err) {
  console.log("ERROR:", e);
  this.body = e;
  return;
}

I have the two questions:

Is there any better place to place index(), i currently have it in the main js file, when the server starts. And i feel it should be in model, but don't know where to put it.

The second question is about catching errors, as you can see i have try/catch block. But it doesn't seem to catch any errors, it doesn't logs or puts in the body. I want to ask what i am doing wrong?

Thanks.

Incorrect syntax in middleware guides

I found this one browsing through the guides.

It currently says

class Post extends Model {
    configure () {
        this.before('create', 'checkIfExists');
    }

    * checkIfExists: function (next) {
        // checking if post with the
        // same title exists in database

        yield next;
    }
}

But it should actually be

class Post extends Model {
    configure () {
        this.before('create', 'checkIfExists');
    }

    * checkIfExists (next) {
        // checking if post with the
        // same title exists in database

        yield next;
    }
}

It is possible to find with $and logic operator

I am trying to find a document in a mongodb collection from two properties. Example:

class Session extends Model {
  getCollection() { 
    return 'sessions';
  }
}

var sessions = yield Session.where(
   { status: 'active' , owner: 'mine'} //by default is applying 'or'
  ).find();

I have tried doing (mongo driver style)

var sessions = yield Session.where(
   { $and: [
      { status: 'active' },
      { owner: 'mine' }
  ]}).find();

but I think it is not supported.
Is there a way to achieve with this library?

Thanks

Plugins?

Do you have tips on implementing Mongoose-style plugins for Mongorito? I would love to port several of our plugins that add methods, statics, and other query helpers in a DRY fashion.

Short id for "_id" doesn't work with .save()

I created my own short id like {_id: "mJTXnQhs", name: "kevin"}, but when trying to .save(), it throw this err:
Argument passed in must be a single String of 12 bytes or a string of 24 hex characters

It's ok if I insert this doc from mongo's shell like this: db.myCollection.insert({_id: "mJTXnQhs", name: "kevin"}).

Then how should I use my own short id for "_id" with mongorito?
Thanks.

btw, mongorito is amazing, it helps a lot.

Defaults, unique...

What is the best way to set some field to have defaults, to be unique, max...?

Find documents by an _ids array

I got a array of users _ids (in string format) and executing something like this:

var usersSelected = [ '5524f7944e335ad923701ee5', '5524f7944e335ad923701ee6' ];
var _projects = yield Project.where('clientLeader').in(usersSelected).find();

return me an empty array for _projects.

But in my db i got a item with one of those _ids

{
    "_id": {
        "$oid": "5525040805b5932c323346fa"
    },
    "clientLeader": {
        "$oid": "5524f7944e335ad923701ee5"
    },...
}

I also tried to do something like this

if (usersSelected.length > 0) {
  usersSelected.forEach(function (clID) {
    clID = ObjectID(clID); 
  });
}

and use the same array in query but result is the same. How can retrieve items made by users in array?

'npm WARN unmet dependency ' error while installing mongorito

$ npm install mongorito --save
npm WARN unmet dependency /Developer/Work/oauth-jwt-server/node_modules/mongorito/node_modules/monk/node_modules/mongodb requires bson@'~0.2' but will load
npm WARN unmet dependency /Developer/Work/oauth-jwt-server/node_modules/mongorito/node_modules/bson,
npm WARN unmet dependency which is version 0.3.2

I have iojs 2.4.0

my package.josn

  "dependencies": {
    "koa": "^0.21.0",
    "koa-bodyparser": "^2.0.1",
    "koa-jwt": "^1.1.1",
    "koa-router": "^5.1.2",
    "mongorito": "^1.3.4"
  }

Pre Query middleware?

Hi there,
I just started using this library and wanted to know if there's a way to execute a function before a query is sent to the database? My use case is that the data in the database is encrypted and I need to encrypt the query object before sending it to the database.

Thanks.

Please understand,My English is very poor

//
Post.find({},{name:1,_id:0})
//results
{ "_id" : ObjectId("551bbfe1ebe85a041dd81c0b"), "name" : "A3" }
{ "_id" : ObjectId("551bc005ebe85a041dd81c0c"), "name" : "A4" }
{ "_id" : ObjectId("551bc01eebe85a041dd81c0d"), "name" : "A4L" }
{ "_id" : ObjectId("551bc025ebe85a041dd81c0e"), "name" : "A6" }
{ "_id" : ObjectId("551bc02cebe85a041dd81c0f"), "name" : "A6L" }
{ "_id" : ObjectId("551bc035ebe85a041dd81c10"), "name" : "Q3" }
.....
// the results Should not include "_id" ,
//I want to get
{ "name" : "A3" }
{ "name" : "A4" }
{ "name" : "A4L" }
{ "name" : "A6" }
{ "name" : "A6L" }
{ "name" : "Q3" }
...

Full API doc

Hi,
thanks for the great work!
I have a question about the documentation, is there is any place with the full API documentation?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.