UNPKG

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