Comparing version 0.0.5 to 1.0.0
@@ -1,12 +0,12 @@ | ||
{ "name": "mongoose" | ||
, "description": "ORM for MongoDB" | ||
, "version": "0.0.5" | ||
, "author": "LearnBoost <dev@learnboost.com>" | ||
, "dependencies": { "mongodb": "0.7.9"} | ||
, "keywords": [ "mongoose", "mongo", "mongodb", "orm", "nosql" ] | ||
, "directories": { "lib": "./lib" } | ||
, "scripts": { "test": "make test" } | ||
, "engines": { "node": ">= 0.1.101" } | ||
, "main": "./mongoose" | ||
, "licenses": [ { "type": "The MIT License", "url": "http://www.opensource.org/licenses/mit-license.php" } ] | ||
{ | ||
"name": "mongoose" | ||
, "description": "Mongoose MongoDB ORM" | ||
, "version": "1.0.0" | ||
, "author": "Guillermo Rauch <guillermo@learnboost.com>" | ||
, "keywords": ["mongodb", "mongoose", "orm", "data", "datastore", "nosql"] | ||
, "dependencies": {} | ||
, "directories": { "lib": "./lib/mongoose" } | ||
, "scripts": { "test": "make test" } | ||
, "main": "./index.js" | ||
, "engines": { "node": ">= 0.2.0" } | ||
} |
494
README.md
@@ -1,397 +0,249 @@ | ||
Mongoose: MongoDB ODM/ORM | ||
========================= | ||
Mongoose 1.0 | ||
============ | ||
The goal of Mongoose is to provide an extremely simple interface for MongoDB. | ||
## What's Mongoose? | ||
## Features | ||
Mongoose is a MongoDB object modeling tool designed to work in an asychronous | ||
environment. | ||
- Reduces the burden of dealing with nested callback from async operations. | ||
- Provides a simple yet rich API. | ||
- Ability to model your data with custom interfaces. | ||
- Allows for complex business logic in an async way (see `Promises`). | ||
Defining a model is as easy as: | ||
## Installation | ||
var Comments = new Schema({ | ||
title : String | ||
, body : String | ||
, date : Date | ||
}); | ||
### As a submodule of your project (recommended) | ||
var BlogPost = new Schema({ | ||
author : ObjectId | ||
, title : String | ||
, body : String | ||
, date : Date | ||
, comments : [Comments] | ||
, meta : { | ||
votes : Number | ||
, favs : Number | ||
} | ||
}); | ||
git submodule add git://github.com/LearnBoost/mongoose.git {path/to/mongoose} | ||
git submodule update --init --recursive | ||
Example paths: `support/mongoose`, `vendor/mongoose`. | ||
### Cloning the repository (mainly for making changes to mongoose) | ||
git clone git://github.com/LearnBoost/mongoose.git --recursive | ||
cd mongoose | ||
### With npm | ||
mongoose.model('BlogPost', BlogPost); | ||
npm install http://github.com/learnboost/mongoose/tree/0.0.2 | ||
### With Kiwi | ||
## Connecting to MongoDB | ||
kiwi install mongoose | ||
## How to use | ||
First, we need to define a connection. If your app uses only one database, you | ||
should use `mongose.connect`. If you need to create additional connections, use | ||
`mongoose.createConnection`. | ||
### Setup | ||
Both `connect` and `createConnection` take a `mongodb://` URI, or the parameters | ||
`host, database, port`. | ||
Simply require Mongoose: | ||
var mongoose = require('mongoose'); | ||
require.paths.unshift('vendor/mongoose'); | ||
var mongoose = require('mongoose').Mongoose; | ||
mongoose.connect('mongodb://localhost/my_database'); | ||
### Defining a model | ||
Once connected, the `open` event is fired on the `Connection` instance. If | ||
you're using `mongoose.connect`, the `Connection` is `mongoose.connection`. | ||
Otherwise, `mongoose.createConnection` return value is a `Connection`. | ||
mongoose.model('User', { | ||
properties: ['first', 'last', 'age', 'updated_at'], | ||
cast: { | ||
age: Number, | ||
'nested.path': String | ||
}, | ||
indexes: ['first'], | ||
setters: { | ||
first: function(v){ | ||
return this.v.capitalize(); | ||
} | ||
}, | ||
getters: { | ||
full_name: function(){ | ||
return this.first + ' ' + this.last | ||
} | ||
}, | ||
methods: { | ||
save: function(fn){ | ||
this.updated_at = new Date(); | ||
this.__super__(fn); | ||
} | ||
}, | ||
static: { | ||
findOldPeople: function(){ | ||
return this.find({age: { '$gt': 70 }}); | ||
} | ||
} | ||
}); | ||
### Getting a model | ||
**Important!** Mongoose buffers all the commands until it's connected to the | ||
database. This means that you don't have to wait until it connects to MongoDB | ||
in order to define models, run queries, etc. | ||
Models are pseudo-classes that depend on an active connection. To connect: | ||
## Defining a Model | ||
var db = mongoose.connect('mongodb://localhost/db'); | ||
To get a model: | ||
var User = db.model('User'); | ||
To create a new instance (document) | ||
Models are defined through the `Schema` interface. | ||
var u = new User(); | ||
u.name = 'John'; | ||
u.save(function(){ | ||
sys.puts('Saved!'); | ||
}); | ||
To fetch some stuff | ||
var Schema = mongoose.Schema | ||
, ObjectId = Schema.ObjectId; | ||
User.find({ name: 'john' }).all(function(array){ | ||
var BlogPost = new Schema({ | ||
author : ObjectId | ||
, title : String | ||
, body : String | ||
, date : Date | ||
}); | ||
### Operating on embedded objects | ||
Aside from defining the structure of your documents and the types of data you're | ||
storing, a Schema handles the definition of: | ||
Embedded objects are hydrated like model instances. Assume a MongoDB document like this stored in a variable `user` | ||
* Validators (async and sync) | ||
* Defaults | ||
* Getters | ||
* Setters | ||
* Indexes | ||
* Middleware | ||
* Methods definition | ||
* Statics definition | ||
* Plugins | ||
{ | ||
name: 'John', | ||
blogposts: [ | ||
{ | ||
title: 'Hi', | ||
body: 'Hi there' | ||
} | ||
] | ||
} | ||
To add a blogpost: | ||
The following example shows some of these features: | ||
user.blogposts.push({ title: 'New post', body: 'The body' }); | ||
user.save(); | ||
var Comment = new Schema({ | ||
name : { type: String, default: 'hahaha' } | ||
, age : { type: Number, min: 18, index: true } | ||
, bio : { type: String, match: /[a-z]/ } | ||
, date : { type: Date, default: Date.now } | ||
}); | ||
To remove an existing one: | ||
// a setter | ||
Comment.path('name').set(function (v) { | ||
return v.capitalize(); | ||
}); | ||
user.blogposts[0] = null; | ||
user.save(); | ||
// middleware | ||
Comment.pre('save', function (next) { | ||
notify(this.get('email')); | ||
next(); | ||
}); | ||
## API | ||
Take a look at the example in `examples/schema.js` for an end-to-end example of | ||
(almost) all the functionality available. | ||
### mongoose | ||
## Accessing a Model | ||
#### Methods | ||
- **model(name, definition)** | ||
- *definition* determines how the class will be constructed. It's composed of the following keys. All of them are optional: | ||
- *collection* | ||
Optionally, the MongoDB collection name. Defaults to the model name in lowercase and plural. Does not need to be created in advance. | ||
- *properties* | ||
Defines the properties for how you structure the model. | ||
To define simple keys: | ||
properties: [ 'name', 'last' ] | ||
To define arrays: | ||
properties: [ 'name', {'tags': []} ] | ||
To define nested objects: | ||
properties: [ 'name', {contact: ['email', 'phone', ...]} ] | ||
To define array of embedded objects: | ||
properties: [ 'name', {blogposts: [['title', 'body', ...]]} ] | ||
`_id` is added automatically for all models. | ||
- *getters* | ||
Defines getters (can be nested). If the getter matches an existing property, the existing value will be passed as the first argument. | ||
- *setters* | ||
Defines setters (can be nested). If the setter matches an existing property, the return value will be set. | ||
- *cast* | ||
Defines type casting. By default, all properties beginning with `_` are cast to `ObjectID`. (note: Casting an Array will cast all items in the Array. Currently, Arrays cast when 'save' is called.) | ||
- *indexes* | ||
An array of indexes. | ||
Simple indexes: ['name', 'last'] | ||
Compound indexes: [{ name: 1, last: 1 }, ...] | ||
Indexes with options: ['simple', [{ name: 1 }, {unique: true}]] | ||
Notice that the objects that you pass are equivalent to those that you would pass to ensureIndex in MongoDB. | ||
- *methods* | ||
Methods that are added to the prototype of the model, or methods that override existing ones. For example `save` (you can call `__super__` to access the parent) | ||
- *static* | ||
Static methods that are not instance-dependent (eg: `findByAge()`) | ||
### Model | ||
Once we define a model through `mongoose.model('ModelName', mySchema)`, we can | ||
access it through the same function | ||
These are methods and properties that all *model instances* already include: | ||
var myModel = mongoose.model('ModelName'); | ||
#### Properties | ||
We can then instantiate it, and save it: | ||
- **isNew** | ||
Whether the instance exists as a document or the db (*false*), or hasn't been saved down before (*true*) | ||
var instance = new myModel(); | ||
myModel.my.key = 'hello'; | ||
myModel.save(function (err) { | ||
// | ||
}); | ||
#### Methods | ||
Or we can find documents from the same collection | ||
Note: if you override any of these by including them in the `methods` object of the model definition, the method is inherited and you can call __super__ to access the parent. | ||
myModel.find({}, function (err, docs) { | ||
// docs.forEach | ||
}); | ||
- **save(fn)** | ||
Saves down the document and fires the callback. | ||
- **remove(fn)** | ||
Removes the document and fires the callback. | ||
### Model (static) | ||
You can also `findOne`, `findById`, `update`, etc. For more details check out | ||
the API docs. | ||
These are the methods that can be accessed statically, and affect the collection as a whole. | ||
## Embedded Documents | ||
- **find(props, subset, hydrate)** | ||
In the first example snippet, we defined a key in the Schema that looks like: | ||
Returns an instance of QueryWriter | ||
comments: [Comments] | ||
- *props* | ||
Optional, calls the QueryWriter `where` on each key/value. `find({username: 'john'})` is equivalent to: | ||
model.find().where('username', 'john'); | ||
- *subset* | ||
Optional, a subset of fields to retrieve. More information on [MongoDB Docs](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-RetrievingaSubsetofFields) | ||
- *hydrate* | ||
Possible values: | ||
- `true`. Returns a model instance (default) | ||
- `null`. Returns a plain object that is augmented to match the missing properties defined in the model. | ||
- `false`. Returns the object as it's retrieved from MongoDB. | ||
Where `Comments` is a `Schema` we created. This means that creating embedded | ||
documents is as simple as: | ||
- **findById(id, fn, hydrate)** | ||
Returns an instance of QueryWriter | ||
- *id* | ||
Document id (hex or string allowed) | ||
- *fn* | ||
Optional callback. Called on success. | ||
- *hydrate* | ||
Same as above | ||
- **update(id, doc, fn)** | ||
// retrieve my model | ||
var BlogPost = mongoose.model('BlogPost'); | ||
Sets/updates *only* the properties of the passed document for the specified object id | ||
// create a blog post | ||
var post = new BlogPost(); | ||
- *id* | ||
Document id (hex or string allowed) | ||
- *fn (doc)* | ||
Optional callback. Called on Success. Doc paramter will contain the hyrdrated document from the DB after the update. | ||
- *hydrate* | ||
Same as above | ||
- **remove(where, fn)** | ||
// create a comment | ||
post.comments.push({ title: 'My comment' }); | ||
Executes the query (and triggers a remove of the matched documents) | ||
post.save(function (err) { | ||
if (!err) console.log('Success!'); | ||
}); | ||
- *where* | ||
Valid where clause. | ||
- *fn* | ||
Optional callback. Called on success. | ||
The same goes for removing them: | ||
### EmbeddedObject | ||
BlogPost.findById(myId, function (err, post) { | ||
if (!err) { | ||
post.comments[0].remove(); | ||
post.save(function (err) { | ||
// do something | ||
}); | ||
} | ||
}); | ||
#### Methods | ||
Embedded documents enjoy all the same features as your models. Defaults, | ||
validators, middleware. Whenever an error occurs, it's bubbled to the `save()` | ||
error callback, so error handling is a snap! | ||
- **remove** | ||
Marks the embeded object for deletion | ||
### QueryWriter | ||
Mongoose interacts with your embedded documents in arrays _atomically_, out of | ||
the box. | ||
QueryWriter allows you to construct queries with very simple syntax. All its methods return the `QueryWriter` instance, which means they're chainable. | ||
## Middleware | ||
#### Methods | ||
Middleware is one of the most exciting features about Mongoose 1.0. Middleware | ||
takes away all the pain of nested callbacks. | ||
##### Executers | ||
Middleware are defined at the Schema level and are applied when the methods | ||
`init` (when a document is initialized with data from MongoDB), `save` (when | ||
a document or embedded document is saved). | ||
These methods execute the query and return a `QueryPromise`. | ||
There's two types of middleware, determined by the signature of the function | ||
you define (ie: the parameters your function accepts): | ||
- **exec** | ||
- Serial | ||
Serial middleware are defined like: | ||
Executes the query. | ||
.pre(method, function (next) { | ||
// ... | ||
}) | ||
- **count** | ||
They're executed one after the other, when each middleware calls `next`. | ||
Executes the query (and triggers a count) | ||
- Parallel | ||
Parallel middleware offer more fine-grained flow control, and are defined | ||
like | ||
In addition, for the sake of simplicity, all the promise methods (see "Queueable methods") are mirrored in the QueryWriter and trigger `.exec()`. Then, the following two are equivalent: | ||
.pre(method, function (next, done) { | ||
// ... | ||
}) | ||
User.find({username: 'john'}).all(fn) | ||
and: | ||
User.find({username: 'john'}).exec().all(fn) | ||
Parallel middleware can `next()` immediately, but the final argument will be | ||
called when all the parallel middleware have called `done()`. | ||
##### Modifiers | ||
- **where** | ||
- **sort** | ||
### Error handling | ||
- **limit** | ||
If any middleware calls `next` or `done` with an `Error` instance, the flow is | ||
interrupted, and the error is passed to the function passed as an argument. | ||
- **skip** | ||
For example: | ||
- **snapshot** | ||
schema.pre('save', function (next) { | ||
// something goes wrong | ||
next(new Error('something went wrong')); | ||
}); | ||
- **group** | ||
// later... | ||
### QueryPromise | ||
A promise is a special object that acts as a `queue` if MongoDB has not resulted the results, and executes the methods you call on it once the results are available. | ||
For example | ||
User.find({ age: { '$gt': 5 } }).first(function(result){ | ||
// gets first result | ||
}).last(function(result){ | ||
// gets last result | ||
myModel.save(function (err) { | ||
// err can come from a middleware | ||
}); | ||
#### Methods | ||
## API docs | ||
- **stash(fn)** | ||
You can find the [Dox](http://github.com/visionmedia/dox) generated API docs at | ||
http://mongoosejs.com. | ||
Stashes all the current queued methods, which will be called when `complete` is called. Methods that are queued **after** stash is called will only fire after `complete` is called again. | ||
## Contributing to Mongoose | ||
- **complete(result)** | ||
### Cloning the repository | ||
Completes the promise. The result parameter is optional. It's either null or an array of documents. (internal use) | ||
Make a fork of `mongoose`, then clone it in your computer. The `master` branch | ||
contains the current stable release, and the `develop` branch the next upcoming | ||
major release. | ||
##### Queueable Methods | ||
If `master` is at `1.0`, `develop` will contain the upcoming `1.1` (or `2.0` if | ||
the `1` branch is nearing its completion). | ||
You can call all of these in a row, but the callbacks will only trigger when `complete is called` | ||
### Guidelines | ||
- **all(fn)** | ||
- Please write inline documentation for new methods or class members. | ||
- Please write tests and make sure your tests pass. | ||
- Before starting to write code, look for existing tickets or create one for | ||
your specifc issue (unless you're addressing something that's clearly broken). | ||
That way you avoid working on something that might not be of interest or that | ||
has been addressed already in a different branch. | ||
Fires with all the results as an array, or an empty array. | ||
- **get(fn)** | ||
Synonym to `all` | ||
- **last(fn)** | ||
Fires with the last document or *null* | ||
- **first(fn)** | ||
Fires with the first document of the resulset or *null* if no documents are returned | ||
- **one(fn)** | ||
Synonym to `first` | ||
## Credits | ||
Nathan White <nathan@learnboost.com> | ||
- Guillermo Rauch - guillermo@learnboost.com - [Guille](http://github.com/guille) | ||
- Nathan White - [nw](http://github.com/nw/) | ||
- Brian Noguchi - [bnoguchi](https://github.com/bnoguchi) | ||
Guillermo Rauch <guillermo@learnboost.com> | ||
## License | ||
## License | ||
(The MIT License) | ||
Copyright (c) 2010 LearnBoost <dev@learnboost.com> | ||
@@ -398,0 +250,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1365507
0
196
0
25456
1
269
2
69
9
- Removedmongodb@0.7.9