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](https://img.shields.io/badge/slack-mongoosejsteam-34D058.svg?logo=slack )](https://mongoosejsteam.slack.com)
6[![Build Status](https://github.com/Automattic/mongoose/workflows/Test/badge.svg)](https://github.com/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
15Mongoose 6.0.0 was released on August 24, 2021. You can find more details on [backwards breaking changes in 6.0.0 on our docs site](https://mongoosejs.com/docs/migrating_to_6.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```
75
76Once 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`.
77
78**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._
79
80**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.
81
82### Defining a Model
83
84Models are defined through the `Schema` interface.
85
86```js
87const Schema = mongoose.Schema;
88const ObjectId = Schema.ObjectId;
89
90const BlogPost = new Schema({
91 author: ObjectId,
92 title: String,
93 body: String,
94  date: Date
95});
96```
97
98Aside from defining the structure of your documents and the types of data you're storing, a Schema handles the definition of:
99
100* [Validators](http://mongoosejs.com/docs/validation.html) (async and sync)
101* [Defaults](http://mongoosejs.com/docs/api.html#schematype_SchemaType-default)
102* [Getters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-get)
103* [Setters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set)
104* [Indexes](http://mongoosejs.com/docs/guide.html#indexes)
105* [Middleware](http://mongoosejs.com/docs/middleware.html)
106* [Methods](http://mongoosejs.com/docs/guide.html#methods) definition
107* [Statics](http://mongoosejs.com/docs/guide.html#statics) definition
108* [Plugins](http://mongoosejs.com/docs/plugins.html)
109* [pseudo-JOINs](http://mongoosejs.com/docs/populate.html)
110
111The following example shows some of these features:
112
113```js
114const Comment = new Schema({
115 name: { type: String, default: 'hahaha' },
116 age: { type: Number, min: 18, index: true },
117 bio: { type: String, match: /[a-z]/ },
118 date: { type: Date, default: Date.now },
119 buff: Buffer
120});
121
122// a setter
123Comment.path('name').set(function (v) {
124 return capitalize(v);
125});
126
127// middleware
128Comment.pre('save', function (next) {
129 notify(this.get('email'));
130 next();
131});
132```
133
134Take 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.
135
136### Accessing a Model
137
138Once we define a model through `mongoose.model('ModelName', mySchema)`, we can access it through the same function
139
140```js
141const MyModel = mongoose.model('ModelName');
142```
143
144Or just do it all at once
145
146```js
147const MyModel = mongoose.model('ModelName', mySchema);
148```
149
150The 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
151
152```js
153const MyModel = mongoose.model('Ticket', mySchema);
154```
155
156Then `MyModel` will use the __tickets__ collection, not the __ticket__ collection. For more details read the [model docs](https://mongoosejs.com/docs/api/mongoose.html#mongoose_Mongoose-model).
157
158Once we have our model, we can then instantiate it, and save it:
159
160```js
161const instance = new MyModel();
162instance.my.key = 'hello';
163instance.save(function (err) {
164 //
165});
166```
167
168Or we can find documents from the same collection
169
170```js
171MyModel.find({}, function (err, docs) {
172 // docs.forEach
173});
174```
175
176You can also `findOne`, `findById`, `update`, etc.
177
178```js
179const instance = await MyModel.findOne({ ... });
180console.log(instance.my.key); // 'hello'
181```
182
183For more details check out [the docs](http://mongoosejs.com/docs/queries.html).
184
185**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:
186
187```js
188const conn = mongoose.createConnection('your connection string');
189const MyModel = conn.model('ModelName', schema);
190const m = new MyModel;
191m.save(); // works
192```
193
194vs
195
196```js
197const conn = mongoose.createConnection('your connection string');
198const MyModel = mongoose.model('ModelName', schema);
199const m = new MyModel;
200m.save(); // does not work b/c the default connection object was never connected
201```
202
203### Embedded Documents
204
205In the first example snippet, we defined a key in the Schema that looks like:
206
207```
208comments: [Comment]
209```
210
211Where `Comment` is a `Schema` we created. This means that creating embedded documents is as simple as:
212
213```js
214// retrieve my model
215const BlogPost = mongoose.model('BlogPost');
216
217// create a blog post
218const post = new BlogPost();
219
220// create a comment
221post.comments.push({ title: 'My comment' });
222
223post.save(function (err) {
224 if (!err) console.log('Success!');
225});
226```
227
228The same goes for removing them:
229
230```js
231BlogPost.findById(myId, function (err, post) {
232 if (!err) {
233 post.comments[0].remove();
234 post.save(function (err) {
235 // do something
236 });
237 }
238});
239```
240
241Embedded 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!
242
243
244### Middleware
245
246See the [docs](http://mongoosejs.com/docs/middleware.html) page.
247
248#### Intercepting and mutating method arguments
249
250You can intercept method arguments via middleware.
251
252For 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:
253
254```js
255schema.pre('set', function (next, path, val, typel) {
256 // `this` is the current Document
257 this.emit('set', path, val);
258
259 // Pass control to the next pre
260 next();
261});
262```
263
264Moreover, 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`:
265
266```js
267.pre(method, function firstPre (next, methodArg1, methodArg2) {
268 // Mutate methodArg1
269 next("altered-" + methodArg1.toString(), methodArg2);
270});
271
272// pre declaration is chainable
273.pre(method, function secondPre (next, methodArg1, methodArg2) {
274 console.log(methodArg1);
275 // => 'altered-originalValOfMethodArg1'
276
277 console.log(methodArg2);
278 // => 'originalValOfMethodArg2'
279
280 // Passing no arguments to `next` automatically passes along the current argument values
281 // i.e., the following `next()` is equivalent to `next(methodArg1, methodArg2)`
282 // and also equivalent to, with the example method arg
283 // values, `next('altered-originalValOfMethodArg1', 'originalValOfMethodArg2')`
284 next();
285});
286```
287
288#### Schema gotcha
289
290`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:
291
292```js
293new Schema({
294 broken: { type: Boolean },
295 asset: {
296 name: String,
297 type: String // uh oh, it broke. asset will be interpreted as String
298 }
299});
300
301new Schema({
302 works: { type: Boolean },
303 asset: {
304 name: String,
305 type: { type: String } // works. asset is an object with a type property
306 }
307});
308```
309
310### Driver Access
311
312Mongoose 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
313notable exception that `YourModel.collection` still buffers
314commands. As such, `YourModel.collection.find()` will **not**
315return a cursor.
316
317## API Docs
318
319Find the API docs [here](http://mongoosejs.com/docs/api.html), generated using [dox](https://github.com/tj/dox)
320and [acquit](https://github.com/vkarpov15/acquit).
321
322## Related Projects
323
324#### MongoDB Runners
325
326- [run-rs](https://www.npmjs.com/package/run-rs)
327- [mongodb-memory-server](https://www.npmjs.com/package/mongodb-memory-server)
328- [mongodb-topology-manager](https://www.npmjs.com/package/mongodb-topology-manager)
329
330#### Unofficial CLIs
331
332- [mongoosejs-cli](https://www.npmjs.com/package/mongoosejs-cli)
333
334#### Data Seeding
335
336- [dookie](https://www.npmjs.com/package/dookie)
337- [seedgoose](https://www.npmjs.com/package/seedgoose)
338- [mongoose-data-seed](https://www.npmjs.com/package/mongoose-data-seed)
339
340#### Express Session Stores
341
342- [connect-mongodb-session](https://www.npmjs.com/package/connect-mongodb-session)
343- [connect-mongo](https://www.npmjs.com/package/connect-mongo)
344
345## License
346
347Copyright (c) 2010 LearnBoost <dev@learnboost.com>
348
349Permission is hereby granted, free of charge, to any person obtaining
350a copy of this software and associated documentation files (the
351'Software'), to deal in the Software without restriction, including
352without limitation the rights to use, copy, modify, merge, publish,
353distribute, sublicense, and/or sell copies of the Software, and to
354permit persons to whom the Software is furnished to do so, subject to
355the following conditions:
356
357The above copyright notice and this permission notice shall be
358included in all copies or substantial portions of the Software.
359
360THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
361EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
362MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
363IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
364CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
365TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
366SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.