UNPKG

13 kBMarkdownView Raw
1# Mongoose
2
3Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. Mongoose supports both promises and callbacks.
4
5[![Slack Status](http://slack.mongoosejs.io/badge.svg)](http://slack.mongoosejs.io)
6[![Build Status](https://api.travis-ci.org/Automattic/mongoose.svg?branch=master)](https://travis-ci.org/Automattic/mongoose)
7[![NPM version](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose)
8
9[![npm](https://nodei.co/npm/mongoose.png)](https://www.npmjs.com/package/mongoose)
10
11## Documentation
12
13The official documentation website is [mongoosejs.com](http://mongoosejs.com/).
14
15[Mongoose 5.0.0](https://github.com/Automattic/mongoose/blob/master/History.md#500--2018-01-17) was released on January 17, 2018. You can find more details on [backwards breaking changes in 5.0.0 on our docs site](https://mongoosejs.com/docs/migrating_to_5.html).
16
17## Support
18
19 - [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoose)
20 - [Bug Reports](https://github.com/Automattic/mongoose/issues/)
21 - [Mongoose Slack Channel](http://slack.mongoosejs.io/)
22 - [Help Forum](http://groups.google.com/group/mongoose-orm)
23 - [MongoDB Support](https://docs.mongodb.org/manual/support/)
24
25## Plugins
26
27Check out the [plugins search site](http://plugins.mongoosejs.io/) to see hundreds of related modules from the community. Next, learn how to write your own plugin from the [docs](http://mongoosejs.com/docs/plugins.html) or [this blog post](http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins).
28
29## Contributors
30
31Pull requests are always welcome! Please base pull requests against the `master`
32branch and follow the [contributing guide](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md).
33
34If your pull requests makes documentation changes, please do **not**
35modify any `.html` files. The `.html` files are compiled code, so please make
36your changes in `docs/*.pug`, `lib/*.js`, or `test/docs/*.js`.
37
38View all 400+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors).
39
40## Installation
41
42First install [Node.js](http://nodejs.org/) and [MongoDB](https://www.mongodb.org/downloads). Then:
43
44```sh
45$ npm install mongoose
46```
47
48## Importing
49
50```javascript
51// Using Node.js `require()`
52const mongoose = require('mongoose');
53
54// Using ES6 imports
55import mongoose from 'mongoose';
56```
57
58## Mongoose for Enterprise
59
60Available as part of the Tidelift Subscription
61
62The maintainers of mongoose and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-mongoose?utm_source=npm-mongoose&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
63
64## Overview
65
66### Connecting to MongoDB
67
68First, we need to define a connection. If your app uses only one database, you should use `mongoose.connect`. If you need to create additional connections, use `mongoose.createConnection`.
69
70Both `connect` and `createConnection` take a `mongodb://` URI, or the parameters `host, database, port, options`.
71
72```js
73await mongoose.connect('mongodb://localhost/my_database', {
74 useNewUrlParser: true,
75 useUnifiedTopology: true
76});
77```
78
79Once 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`.
80
81**Note:** _If the local connection fails then try using 127.0.0.1 instead of localhost. Sometimes issues may arise when the local hostname has been changed._
82
83**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.
84
85### Defining a Model
86
87Models are defined through the `Schema` interface.
88
89```js
90const Schema = mongoose.Schema;
91const ObjectId = Schema.ObjectId;
92
93const BlogPost = new Schema({
94 author: ObjectId,
95 title: String,
96 body: String,
97  date: Date
98});
99```
100
101Aside from defining the structure of your documents and the types of data you're storing, a Schema handles the definition of:
102
103* [Validators](http://mongoosejs.com/docs/validation.html) (async and sync)
104* [Defaults](http://mongoosejs.com/docs/api.html#schematype_SchemaType-default)
105* [Getters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-get)
106* [Setters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set)
107* [Indexes](http://mongoosejs.com/docs/guide.html#indexes)
108* [Middleware](http://mongoosejs.com/docs/middleware.html)
109* [Methods](http://mongoosejs.com/docs/guide.html#methods) definition
110* [Statics](http://mongoosejs.com/docs/guide.html#statics) definition
111* [Plugins](http://mongoosejs.com/docs/plugins.html)
112* [pseudo-JOINs](http://mongoosejs.com/docs/populate.html)
113
114The following example shows some of these features:
115
116```js
117const Comment = new Schema({
118 name: { type: String, default: 'hahaha' },
119 age: { type: Number, min: 18, index: true },
120 bio: { type: String, match: /[a-z]/ },
121 date: { type: Date, default: Date.now },
122 buff: Buffer
123});
124
125// a setter
126Comment.path('name').set(function (v) {
127 return capitalize(v);
128});
129
130// middleware
131Comment.pre('save', function (next) {
132 notify(this.get('email'));
133 next();
134});
135```
136
137Take a look at the example in [`examples/schema/schema.js`](https://github.com/Automattic/mongoose/blob/master/examples/schema/schema.js) for an end-to-end example of a typical setup.
138
139### Accessing a Model
140
141Once we define a model through `mongoose.model('ModelName', mySchema)`, we can access it through the same function
142
143```js
144const MyModel = mongoose.model('ModelName');
145```
146
147Or just do it all at once
148
149```js
150const MyModel = mongoose.model('ModelName', mySchema);
151```
152
153The first argument is the _singular_ name of the collection your model is for. **Mongoose automatically looks for the _plural_ version of your model name.** For example, if you use
154
155```js
156const MyModel = mongoose.model('Ticket', mySchema);
157```
158
159Then Mongoose will create the model for your __tickets__ collection, not your __ticket__ collection.
160
161Once we have our model, we can then instantiate it, and save it:
162
163```js
164const instance = new MyModel();
165instance.my.key = 'hello';
166instance.save(function (err) {
167 //
168});
169```
170
171Or we can find documents from the same collection
172
173```js
174MyModel.find({}, function (err, docs) {
175 // docs.forEach
176});
177```
178
179You can also `findOne`, `findById`, `update`, etc.
180
181```js
182const instance = await MyModel.findOne({ ... });
183console.log(instance.my.key); // 'hello'
184```
185
186For more details check out [the docs](http://mongoosejs.com/docs/queries.html).
187
188**Important!** If you opened a separate connection using `mongoose.createConnection()` but attempt to access the model through `mongoose.model('ModelName')` it will not work as expected since it is not hooked up to an active db connection. In this case access your model through the connection you created:
189
190```js
191const conn = mongoose.createConnection('your connection string');
192const MyModel = conn.model('ModelName', schema);
193const m = new MyModel;
194m.save(); // works
195```
196
197vs
198
199```js
200const conn = mongoose.createConnection('your connection string');
201const MyModel = mongoose.model('ModelName', schema);
202const m = new MyModel;
203m.save(); // does not work b/c the default connection object was never connected
204```
205
206### Embedded Documents
207
208In the first example snippet, we defined a key in the Schema that looks like:
209
210```
211comments: [Comment]
212```
213
214Where `Comment` is a `Schema` we created. This means that creating embedded documents is as simple as:
215
216```js
217// retrieve my model
218const BlogPost = mongoose.model('BlogPost');
219
220// create a blog post
221const post = new BlogPost();
222
223// create a comment
224post.comments.push({ title: 'My comment' });
225
226post.save(function (err) {
227 if (!err) console.log('Success!');
228});
229```
230
231The same goes for removing them:
232
233```js
234BlogPost.findById(myId, function (err, post) {
235 if (!err) {
236 post.comments[0].remove();
237 post.save(function (err) {
238 // do something
239 });
240 }
241});
242```
243
244Embedded 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!
245
246
247### Middleware
248
249See the [docs](http://mongoosejs.com/docs/middleware.html) page.
250
251#### Intercepting and mutating method arguments
252
253You can intercept method arguments via middleware.
254
255For example, this would allow you to broadcast changes about your Documents every time someone `set`s a path in your Document to a new value:
256
257```js
258schema.pre('set', function (next, path, val, typel) {
259 // `this` is the current Document
260 this.emit('set', path, val);
261
262 // Pass control to the next pre
263 next();
264});
265```
266
267Moreover, you can mutate the incoming `method` arguments so that subsequent middleware see different values for those arguments. To do so, just pass the new values to `next`:
268
269```js
270.pre(method, function firstPre (next, methodArg1, methodArg2) {
271 // Mutate methodArg1
272 next("altered-" + methodArg1.toString(), methodArg2);
273});
274
275// pre declaration is chainable
276.pre(method, function secondPre (next, methodArg1, methodArg2) {
277 console.log(methodArg1);
278 // => 'altered-originalValOfMethodArg1'
279
280 console.log(methodArg2);
281 // => 'originalValOfMethodArg2'
282
283 // Passing no arguments to `next` automatically passes along the current argument values
284 // i.e., the following `next()` is equivalent to `next(methodArg1, methodArg2)`
285 // and also equivalent to, with the example method arg
286 // values, `next('altered-originalValOfMethodArg1', 'originalValOfMethodArg2')`
287 next();
288});
289```
290
291#### Schema gotcha
292
293`type`, when used in a schema has special meaning within Mongoose. If your schema requires using `type` as a nested property you must use object notation:
294
295```js
296new Schema({
297 broken: { type: Boolean },
298 asset: {
299 name: String,
300 type: String // uh oh, it broke. asset will be interpreted as String
301 }
302});
303
304new Schema({
305 works: { type: Boolean },
306 asset: {
307 name: String,
308 type: { type: String } // works. asset is an object with a type property
309 }
310});
311```
312
313### Driver Access
314
315Mongoose is built on top of the [official MongoDB Node.js driver](https://github.com/mongodb/node-mongodb-native). Each mongoose model keeps a reference to a [native MongoDB driver collection](http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html). The collection object can be accessed using `YourModel.collection`. However, using the collection object directly bypasses all mongoose features, including hooks, validation, etc. The one
316notable exception that `YourModel.collection` still buffers
317commands. As such, `YourModel.collection.find()` will **not**
318return a cursor.
319
320## API Docs
321
322Find the API docs [here](http://mongoosejs.com/docs/api.html), generated using [dox](https://github.com/tj/dox)
323and [acquit](https://github.com/vkarpov15/acquit).
324
325## Related Projects
326
327#### MongoDB Runners
328
329- [run-rs](https://www.npmjs.com/package/run-rs)
330- [mongodb-memory-server](https://www.npmjs.com/package/mongodb-memory-server)
331- [mongodb-topology-manager](https://www.npmjs.com/package/mongodb-topology-manager)
332
333#### Unofficial CLIs
334
335- [mongoosejs-cli](https://www.npmjs.com/package/mongoosejs-cli)
336
337#### Data Seeding
338
339- [dookie](https://www.npmjs.com/package/dookie)
340- [seedgoose](https://www.npmjs.com/package/seedgoose)
341- [mongoose-data-seed](https://www.npmjs.com/package/mongoose-data-seed)
342
343#### Express Session Stores
344
345- [connect-mongodb-session](https://www.npmjs.com/package/connect-mongodb-session)
346- [connect-mongo](https://www.npmjs.com/package/connect-mongo)
347
348## License
349
350Copyright (c) 2010 LearnBoost <dev@learnboost.com>
351
352Permission is hereby granted, free of charge, to any person obtaining
353a copy of this software and associated documentation files (the
354'Software'), to deal in the Software without restriction, including
355without limitation the rights to use, copy, modify, merge, publish,
356distribute, sublicense, and/or sell copies of the Software, and to
357permit persons to whom the Software is furnished to do so, subject to
358the following conditions:
359
360The above copyright notice and this permission notice shall be
361included in all copies or substantial portions of the Software.
362
363THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
364EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
365MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
366IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
367CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
368TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
369SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.