Skip to content
This repository has been archived by the owner on Feb 10, 2022. It is now read-only.

Commit

Permalink
v0.2.0 - added automatic caching
Browse files Browse the repository at this point in the history
  • Loading branch information
Vadim Demedes committed Feb 18, 2012
1 parent 10120fd commit 358a47d
Show file tree
Hide file tree
Showing 5 changed files with 427 additions and 168 deletions.
21 changes: 21 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

*Awesome* MongoDB ODM for Node.js. Just take a look on its pretty models. Uses Mongolian for interacting with MongoDB.

# Features

- Define models, and operate with them just like usual objects, forget about documentation
- Built-in caching, using [Memcacher](https://github.com/vdemedes/memcacher)
- Based on Mongolian
- Super-fast, lightweight, all codebase is in one file
- Covered by tests
- Used in production projects
- Active development

# Installation

```
Expand All @@ -14,6 +24,7 @@ npm install mongorito
Mongorito = require 'mongorito'

Mongorito.connect 'database', ['127.0.0.1:27017'], 'user', 'password'
Mongorito.cache ['127.0.0.1:11211'] # optional, allows automatic, smart caching. It is just one line to enable it!

class Post
constructor: ->
Expand Down Expand Up @@ -52,6 +63,7 @@ Nothing special, you will just have to use dirtier syntax, but that's ok.
var Mongorito = require('mongorito');

Mongorito.connect('database', ['127.0.0.1:27017'], 'user', 'password');
Mongorito.cache(['127.0.0.1:11211']);

var Post = (function(){

Expand Down Expand Up @@ -81,6 +93,15 @@ Post.find(function(err, posts){
});
```

# Tests

Tests made using Mocha. Run using:

```
cd tests && mocha *
```


# License

(The MIT License)
Expand Down
216 changes: 145 additions & 71 deletions lib/mongorito.coffee
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
mongolian = require 'mongolian'
async = require 'async'
memcacher = require 'memcacher'
Client = undefined
Cache = undefined

`String.prototype.plural = function() {
var s = this.trim().toLowerCase();
Expand Down Expand Up @@ -84,6 +86,9 @@ class Mongorito
error: ->
Client.auth username, password if username

@cache: (servers = []) ->
Cache = new memcacher servers

@bake: (model) ->
extendsClass(model, MongoritoModel)
object = new model
Expand All @@ -102,22 +107,43 @@ class MongoritoModel
fields[field] = @[field] if -1 is notFields.indexOf field
fields

@bakeModelsFromItems: (items, _model) ->
models = []
for item in items
item._id = item._id.toString()
model = new _model
model.collection = _model.collection
for field of item
model[field] = item[field]
models.push model
models

@findById: (id, callback) ->
that = @

Client.collection(@collection).find({ _id: new mongolian.ObjectId(id.toString()) }).toArray (err, item) ->
if item.length is 0
item = item[0]
item._id = item._id.toString()
model = new that.model
model.collection = that.collection
for field of item
model[field] = item[field]
query = (id, done) ->
Client.collection(that.collection).find({ _id: new mongolian.ObjectId(id.toString()) }).toArray (err, items) ->
process.nextTick ->
done err, items

if not Cache
return query id, (err, items) ->
models = that.bakeModelsFromItems items, that.model
callback err, models[0]

key = "#{ @collection }-#{ id.toString() }"

Cache.get key, (err, result) ->
if not result
query id, (err, items) ->
Cache.set key, JSON.stringify(items), 2592000, [that.collection], ->
models = that.bakeModelsFromItems items, that.model
process.nextTick ->
callback err, models
else
model = no

process.nextTick ->
callback err, model
models = that.bakeModelsFromItems JSON.parse(result), that.model
process.nextTick ->
callback err, models

@findWithOrderAndLimit: (criteria, order, limit, skip, callback) ->
if typeof criteria is 'object'
Expand All @@ -138,18 +164,29 @@ class MongoritoModel
skip = 0 if not skip
that = @

Client.collection(@collection).find(criteria).sort(order).limit(limit).skip(skip).toArray (err, items) ->
models = []
for item in items
item._id = item._id.toString()
model = new that.model
model.collection = that.collection
for field of item
model[field] = item[field]
models.push model

process.nextTick ->
callback err, models
query = (criteria, order, limit, skip, done) ->
Client.collection(that.collection).find(criteria).sort(order).limit(limit).skip(skip).toArray (err, items) ->
done err, items

if not Cache
return query criteria, order, limit, skip, (err, items) ->
models = that.bakeModelsFromItems items, that.model
process.nextTick ->
callback err, models

key = "#{ @collection }-order-#{ order }-limit-#{ limit }-skip-#{ skip }-#{ JSON.stringify(criteria) }"

Cache.get key, (err, result) ->
if not result
query criteria, order, limit, skip, (err, items) ->
Cache.set key, JSON.stringify(items), 2592000, [that.collection], ->
models = that.bakeModelsFromItems items, that.model
process.nextTick ->
callback err, models
else
models = that.bakeModelsFromItems JSON.parse(result), that.model
process.nextTick ->
callback err, models

@findWithOrder: (criteria, order, callback) ->
if typeof criteria is 'object' and typeof order is 'function'
Expand All @@ -160,18 +197,29 @@ class MongoritoModel

that = @

Client.collection(@collection).find(criteria).sort(order).toArray (err, items) ->
models = []
for item in items
item._id = item._id.toString()
model = new that.model
model.collection = that.collection
for field of item
model[field] = item[field]
models.push model

process.nextTick ->
callback err, models
query = (criteria, order, done) ->
Client.collection(that.collection).find(criteria).sort(order).toArray (err, items) ->
done err, items

if not Cache
return query criteria, order, (err, items) ->
models = that.bakeModelsFromItems items, that.model
process.nextTick ->
callback err, models

key = "#{ @collection }-order-#{ order }-#{ JSON.stringify(criteria) }"

Cache.get key, (err, result) ->
if not result
query criteria, order, (err, items) ->
Cache.set key, JSON.stringify(items), 2592000, [that.collection], ->
models = that.bakeModelsFromItems items, that.model
process.nextTick ->
callback err, models
else
models = that.bakeModelsFromItems JSON.parse(result), that.model
process.nextTick ->
callback err, models

@findWithLimit: (criteria, limit, skip, callback) ->
if typeof criteria is 'number'
Expand All @@ -194,18 +242,30 @@ class MongoritoModel

that = @

Client.collection(@collection).find(criteria).limit(limit).skip(skip).toArray (err, items) ->
models = []
for item in items
item._id = item._id.toString()
model = new that.model
model.collection = that.collection
for field of item
model[field] = item[field]
models.push model

process.nextTick ->
callback err, models
query = (criteria, limit, skip, done) ->
Client.collection(that.collection).find(criteria).limit(limit).skip(skip).toArray (err, items) ->
process.nextTick ->
done err, items

if not Cache
return query criteria, limit, skip, (err, items) ->
models = that.bakeModelsFromItems items, that.model
process.nextTick ->
callback err, models

key = "#{ @collection }-limit-#{ limit }-skip-#{ skip }-#{ JSON.stringify(criteria) }"

Cache.get key, (err, result) ->
if not result
query criteria, limit, skip, (err, items) ->
Cache.set key, JSON.stringify(items), 2592000, [that.collection], ->
models = that.bakeModelsFromItems items, that.model
process.nextTick ->
callback err, models
else
models = that.bakeModelsFromItems JSON.parse(result), that.model
process.nextTick ->
callback err, models

@find: (criteria = {}, callback) ->
if typeof(criteria) is 'function'
Expand All @@ -214,22 +274,34 @@ class MongoritoModel

that = @

Client.collection(@collection).find(criteria).toArray (err, items) ->
models = []
for item in items
item._id = item._id.toString()
model = new that.model
model.collection = that.collection
for field of item
model[field] = item[field]
models.push model

process.nextTick ->
callback err, models
query = (criteria, done) ->
Client.collection(that.collection).find(criteria).toArray (err, items) ->
process.nextTick ->
done err, items

if not Cache
return query criteria, (err, items) ->
models = that.bakeModelsFromItems items, that.model
process.nextTick ->
callback err, models

key = "#{ @collection }-#{ JSON.stringify(criteria) }"

Cache.get key, (err, result) ->
if not result
query criteria, (err, items) ->
models = that.bakeModelsFromItems items, that.model
Cache.set key, JSON.stringify(items), 2592000, [that.collection], ->
process.nextTick ->
callback err, models
else
models = that.bakeModelsFromItems JSON.parse(result), that.model
process.nextTick ->
callback err, models

save: (callback) ->
that = @
fields = @fields
fields = do @fields

notFields = ['constructor', 'save', 'collection', 'create', 'fields', 'update', 'remove', 'models']
keys = []
Expand All @@ -245,10 +317,11 @@ class MongoritoModel
, (results) ->
return callback yes, results if results.length > 0

if fields._id
that.update callback, yes
else
that.create callback, yes
Cache.delByTag that.collection, ->
if fields._id
that.update callback, yes
else
that.create callback, yes

create: (callback, fromSave = no) ->
object = @fields()
Expand Down Expand Up @@ -288,18 +361,19 @@ class MongoritoModel
do @beforeRemove if @['beforeRemove']
do @aroundRemove if @['aroundRemove']
that = @

Client.collection(@collection).remove { _id: _id }, (err) ->
do that.aroundRemove if that['aroundRemove']
do that.afterRemove if that['afterRemove']
process.nextTick ->
callback err if callback
Cache.delByTag @collection, ->
Client.collection(that.collection).remove { _id: _id }, (err) ->
do that.aroundRemove if that['aroundRemove']
do that.afterRemove if that['afterRemove']
process.nextTick ->
callback err if callback


class GenericModel extends MongoritoModel

module.exports=
connect: Mongorito.connect
disconnect: Mongorito.disconnect
cache: Mongorito.cache
bake: Mongorito.bake
Model: MongoritoModel
Loading

0 comments on commit 358a47d

Please sign in to comment.