What is mongoose?
Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It manages relationships between data, provides schema validation, and is used to translate between objects in code and the representation of those objects in MongoDB.
What are mongoose's main functionalities?
Schema Definition
Defines a schema for a collection with various field types, validation, and defaults.
{"const mongoose = require('mongoose');\nconst Schema = mongoose.Schema;\nconst blogSchema = new Schema({\n title: String,\n author: String,\n body: String,\n comments: [{ body: String, date: Date }],\n date: { type: Date, default: Date.now },\n hidden: Boolean,\n meta: {\n votes: Number,\n favs: Number\n }\n});"}
Model Creation
Creates a model based on a defined schema, which can then be used to create, read, update, and delete documents of that schema type.
{"const mongoose = require('mongoose');\nconst Blog = mongoose.model('Blog', blogSchema);"}
Connection to MongoDB
Establishes a connection to a MongoDB database.
{"const mongoose = require('mongoose');\nmongoose.connect('mongodb://localhost/my_database', {useNewUrlParser: true, useUnifiedTopology: true});"}
Querying
Queries the database for documents matching certain criteria.
{"Blog.find({ author: 'John Doe' }).exec((err, blogs) => {\n if (err) return handleError(err);\n console.log('The blogs are', blogs);\n});"}
Data Validation
Ensures that the data being saved to the database meets certain criteria defined in the schema.
{"const personSchema = new Schema({\n name: {\n type: String,\n required: true\n },\n age: {\n type: Number,\n min: 18,\n max: 65\n }\n});"}
Middleware (Hooks)
Allows execution of code before or after certain actions, such as saving a document.
{"blogSchema.pre('save', function(next) {\n if (!this.isModified('title')) {\n return next();\n }\n this.modifiedAt = Date.now();\n next();\n});"}
Other packages similar to mongoose
sequelize
Sequelize is a promise-based Node.js ORM for Postgres, MySQL, MariaDB, SQLite, and Microsoft SQL Server. It features solid transaction support, relations, eager and lazy loading, read replication and more. Unlike Mongoose, which is designed for MongoDB, Sequelize is used for relational databases.
typeorm
TypeORM is an ORM that can run in Node.js and be used with TypeScript and JavaScript (ES5, ES6, ES7, ES8). It supports both Active Record and Data Mapper patterns, unlike Mongoose which is primarily schema-based. TypeORM works with SQL databases like MySQL, PostgreSQL, and SQLite.
waterline
Waterline is a data store-agnostic ORM that is bundled in the Sails.js framework but can also be used separately. It provides a uniform API for accessing different kinds of databases, including both SQL and NoSQL, and thus offers more flexibility compared to Mongoose which is MongoDB-specific.
bookshelf
Bookshelf is a JavaScript ORM for Node.js, built on the Knex SQL query builder. It features both promise-based and traditional callback interfaces, transaction support, and eager/nested-eager relation loading. Bookshelf is designed for relational databases and thus is a different choice compared to Mongoose for MongoDB.
Mongoose: MongoDB ODM/ORM
The goal of Mongoose is to provide a extremely simple interface for MongoDB.
Features
- 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
).
Installation
As a submodule of your project (recommended)
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
npm install http://github.com/learnboost/mongoose/tree/0.0.2
With Kiwi
kiwi install mongoose
How to use
Setup
Simply require Mongoose:
require.paths.unshift('vendor/mongoose');
var mongoose = require('mongoose').Mongoose;
Defining a model
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
Models are pseudo-classes that depend on an active connection. To connect:
var db = mongoose.connect('mongodb://localhost/db');
To get a model:
var User = db.model('User');
To create a new instance (document)
var u = new User();
u.name = 'John';
u.save(function(){
sys.puts('Saved!');
});
To fetch some stuff
User.find({ name: 'john' }).all(function(array){
});
Operating on embedded objects
Embedded objects are hydrated like model instances. Assume a MongoDB document like this stored in a variable user
{
name: 'John',
blogposts: [
{
title: 'Hi',
body: 'Hi there'
}
]
}
To add a blogpost:
user.blogposts.push({ title: 'New post', body: 'The body' });
user.save();
To remove an existing one:
user.blogposts[0] = null;
user.save();
API
mongoose
Methods
Model
These are methods and properties that all model instances already include:
Properties
Methods
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.
Model (static)
These are the methods that can be accessed statically, and affect the collection as a whole.
-
find(props, subset, hydrate)
Returns an instance of QueryWriter
-
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
-
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.
-
findById(id, fn, hydrate)
Returns an instance of QueryWriter
-
update(id, doc, fn)
Sets/updates only the properties of the passed document for the specified object id
-
remove(where, fn)
Executes the query (and triggers a remove of the matched documents)
EmbeddedObject
Methods
QueryWriter
QueryWriter allows you to construct queries with very simple syntax. All its methods return the QueryWriter
instance, which means they're chainable.
Methods
Executers
These methods execute the query and return a QueryPromise
.
-
exec
Executes the query.
-
count
Executes the query (and triggers a count)
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:
User.find({username: 'john'}).all(fn)
and:
User.find({username: 'john'}).exec().all(fn)
Modifiers
-
where
-
sort
-
limit
-
skip
-
snapshot
-
group
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
});
Methods
-
stash(fn)
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.
-
complete(result)
Completes the promise. The result parameter is optional. It's either null or an array of documents. (internal use)
Queueable Methods
You can call all of these in a row, but the callbacks will only trigger when complete is called
-
all(fn)
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>
License
(The MIT License)
Copyright (c) 2010 LearnBoost <dev@learnboost.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.