Automattic/mongoose

GitHub: Automattic/mongoose

为 Node.js 和 Deno 提供异步 MongoDB 对象建模能力的 ODM 库,通过 Schema 定义和丰富的中间件机制简化数据库交互。

Stars: 27461 | Forks: 3987

# Mongoose Mongoose 是一个专为异步环境设计的 [MongoDB](https://www.mongodb.org/) 对象建模工具。Mongoose 支持 [Node.js](https://nodejs.org/en/) 和 [Deno](https://deno.land/)(alpha 版本)。 [![构建状态](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/ad66e89bee140833.svg)](https://github.com/Automattic/mongoose) [![NPM 版本](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose) [![Deno 版本](https://deno.land/badge/mongoose/version)](https://deno.land/x/mongoose) [![Deno 流行度](https://deno.land/badge/mongoose/popularity)](https://deno.land/x/mongoose) [![npm](https://nodei.co/npm/mongoose.png)](https://www.npmjs.com/package/mongoose) ## 文档 官方文档网站是 [mongoosejs.com](https://mongoosejs.com/)。 Mongoose 9.0.0 于 2025 年 11 月 21 日发布。您可以在[我们文档网站上的 9.0.0 向后不兼容变更](https://mongoosejs.com/docs/migrating_to_9.html)中了解更多详情。 ## 支持 * [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoose) * [错误报告](https://github.com/Automattic/mongoose/issues/) * [Mongoose Slack 频道](http://slack.mongoosejs.io/) * [帮助论坛](http://groups.google.com/group/mongoose-orm) * [MongoDB 支持](https://www.mongodb.com/docs/manual/support/) ## 插件 请查看[插件搜索网站](https://plugins.mongoosejs.io/)以获取社区提供的数百个相关模块。接下来,您可以通过[文档](https://mongoosejs.com/docs/plugins.html)或[这篇博文](http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins)学习如何编写自己的插件。 ## 安装说明 首先安装 [Node.js](https://nodejs.org/) 和 [MongoDB](https://www.mongodb.org/downloads),然后使用您首选的包管理器安装 `mongoose` 包: ### 使用 npm ``` npm install mongoose ``` ### 使用 pnpm ``` pnpm add mongoose ``` ### 使用 Yarn ``` yarn add mongoose ``` ### 使用 Bun ``` bun add mongoose ``` Mongoose 6.8.0 还包含对 [Deno](https://deno.land/) 的 alpha 支持。 ## 导入 ``` // Using Node.js `require()` const mongoose = require('mongoose'); // Using ES6 imports import mongoose from 'mongoose'; ``` 或者,如下所示,使用 [Deno 的 `createRequire()` 来支持 CommonJS](https://deno.land/std@0.113.0/node/README.md?source=#commonjs-modules-loading)。 ``` import { createRequire } from 'https://deno.land/std@0.177.0/node/module.ts'; const require = createRequire(import.meta.url); const mongoose = require('mongoose'); mongoose.connect('mongodb://127.0.0.1:27017/test') .then(() => console.log('Connected!')); ``` 然后您可以使用以下命令运行上述脚本。 ``` deno run --allow-net --allow-read --allow-sys --allow-env mongoose-test.js ``` ## Mongoose 企业版 作为 Tidelift 订阅的一部分提供 Mongoose 的维护者以及成千上万的其他包的维护者正在与 Tidelift 合作,为您用于构建应用程序的开源依赖项提供商业支持和维护。节省时间,降低风险并改善代码健康状况,同时为您确切使用的依赖项的维护者提供报酬。[了解更多。](https://tidelift.com/subscription/pkg/npm-mongoose?utm_source=npm-mongoose&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) ## 概述 ### 连接到 MongoDB 首先,我们需要定义一个连接。如果您的应用程序只使用一个数据库,您应该使用 `mongoose.connect`。如果您需要创建额外的连接,请使用 `mongoose.createConnection`。 `connect` 和 `createConnection` 都接受一个 `mongodb://` URI,或者参数 `host, database, port, options`。 ``` await mongoose.connect('mongodb://127.0.0.1/my_database'); ``` 一旦连接成功,`Connection` 实例就会触发 `open` 事件。如果您使用的是 `mongoose.connect`,该 `Connection` 就是 `mongoose.connection`。否则,`mongoose.createConnection` 的返回值就是一个 `Connection`。 **注意:** *如果本地连接失败,请尝试使用 `127.0.0.1` 代替 `localhost`。有时当本地主机名被更改时会出现问题。* **重要!** Mongoose 会缓冲所有命令,直到它连接到数据库。这意味着您不必等到它连接到 MongoDB 后才能定义模型、运行查询等。 ### 定义模型 模型是通过 `Schema` 接口定义的。 ``` const Schema = mongoose.Schema; const ObjectId = Schema.ObjectId; const BlogPost = new Schema({ author: ObjectId, title: String, body: String, date: Date }); ``` 除了定义文档的结构和您存储的数据类型之外,Schema 还处理以下内容的定义: * [验证器](https://mongoosejs.com/docs/validation.html)(异步和同步) * [默认值](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-default) * [Getter](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-get) * [Setter](https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-set) * [索引](https://mongoosejs.com/docs/guide.html#indexes) * [中间件](https://mongoosejs.com/docs/middleware.html) * [方法](https://mongoosejs.com/docs/guide.html#methods)定义 * [静态方法](https://mongoosejs.com/docs/guide.html#statics)定义 * [插件](https://mongoosejs.com/docs/plugins.html) * [伪 JOIN](https://mongoosejs.com/docs/populate.html) 以下示例展示了其中一些特性: ``` const 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 }, buff: Buffer }); // a setter Comment.path('name').set(function(v) { return capitalize(v); }); // middleware Comment.pre('save', function(next) { notify(this.get('email')); next(); }); ``` 请查看 [`examples/schema/schema.js`](https://github.com/Automattic/mongoose/blob/master/examples/schema/schema.js) 中的示例,以获取典型设置的端到端示例。 ### 访问模型 一旦我们通过 `mongoose.model('ModelName', mySchema)` 定义了一个模型,我们就可以通过相同的函数来访问它 ``` const MyModel = mongoose.model('ModelName'); ``` 或者一步到位完成所有操作 ``` const MyModel = mongoose.model('ModelName', mySchema); ``` 第一个参数是您的模型对应的集合的*单数*名称。**Mongoose 会自动查找您的模型名称的*复数*版本。** 例如,如果您使用 ``` const MyModel = mongoose.model('Ticket', mySchema); ``` 那么 `MyModel` 将使用 **tickets** 集合,而不是 **ticket** 集合。有关更多详细信息,请阅读[模型文档](https://mongoosejs.com/docs/api/mongoose.html#mongoose_Mongoose-model)。 一旦我们有了模型,我们就可以实例化它,并将其保存: ``` const instance = new MyModel(); instance.my.key = 'hello'; await instance.save(); ``` 或者我们也可以从同一个集合中查找文档 ``` await MyModel.find({}); ``` 您还可以使用 `findOne`、`findById`、`update` 等。 ``` const instance = await MyModel.findOne({ /* ... */ }); console.log(instance.my.key); // 'hello' ``` 有关更多详细信息,请查看[文档](https://mongoosejs.com/docs/queries.html)。 **重要!** 如果您使用 `mongoose.createConnection()` 打开了一个单独的连接,但尝试通过 `mongoose.model('ModelName')` 访问模型,它将无法按预期工作,因为它没有挂钩到活动的数据库连接。在这种情况下,请通过您创建的连接访问您的模型: ``` const conn = mongoose.createConnection('your connection string'); const MyModel = conn.model('ModelName', schema); const m = new MyModel(); await m.save(); // works ``` 对比 ``` const conn = mongoose.createConnection('your connection string'); const MyModel = mongoose.model('ModelName', schema); const m = new MyModel(); await m.save(); // does not work b/c the default connection object was never connected ``` ### 嵌入文档 在第一个示例代码片段中,我们在 Schema 中定义了一个如下所示的键: ``` comments: [Comment] ``` 其中 `Comment` 是我们创建的一个 `Schema`。这意味着创建嵌入文档就像这样简单: ``` // retrieve my model const BlogPost = mongoose.model('BlogPost'); // create a blog post const post = new BlogPost(); // create a comment post.comments.push({ title: 'My comment' }); await post.save(); ``` 删除它们也是同理: ``` const post = await BlogPost.findById(myId); post.comments[0].deleteOne(); await post.save(); ``` 嵌入文档享有与您的模型相同的所有特性。默认值、验证器、中间件。 ### 中间件 请参阅[文档](https://mongoosejs.com/docs/middleware.html)页面。 #### 拦截和修改方法参数 您可以通过中间件拦截方法参数。 例如,这将允许您在每次有人将文档中的某个路径 `set` 为新值时,广播有关您的 Documents 的更改: ``` schema.pre('set', function(next, path, val, typel) { // `this` is the current Document this.emit('set', path, val); // Pass control to the next pre next(); }); ``` 此外,您可以修改传入的 `method` 参数,以便后续的中间件看到这些参数的不同值。为此,只需将新值传递给 `next`: ``` schema.pre(method, function firstPre(next, methodArg1, methodArg2) { // Mutate methodArg1 next('altered-' + methodArg1.toString(), methodArg2); }); // pre declaration is chainable schema.pre(method, function secondPre(next, methodArg1, methodArg2) { console.log(methodArg1); // => 'altered-originalValOfMethodArg1' console.log(methodArg2); // => 'originalValOfMethodArg2' // Passing no arguments to `next` automatically passes along the current argument values // i.e., the following `next()` is equivalent to `next(methodArg1, methodArg2)` // and also equivalent to, with the example method arg // values, `next('altered-originalValOfMethodArg1', 'originalValOfMethodArg2')` next(); }); ``` #### Schema 注意事项 `type` 在 schema 中使用时,在 Mongoose 中具有特殊含义。如果您的 schema 需要将 `type` 用作嵌套属性,您必须使用对象表示法: ``` new Schema({ broken: { type: Boolean }, asset: { name: String, type: String // uh oh, it broke. asset will be interpreted as String } }); new Schema({ works: { type: Boolean }, asset: { name: String, type: { type: String } // works. asset is an object with a type property } }); ``` ### 驱动程序访问 Mongoose 构建在 [MongoDB 官方 Node.js 驱动程序](https://github.com/mongodb/node-mongodb-native)之上。每个 Mongoose 模型都保留对[原生 MongoDB 驱动程序集合](http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html)的引用。可以使用 `YourModel.collection` 访问该集合对象。然而,直接使用集合对象会绕过所有 Mongoose 特性,包括钩子、验证等。一个 值得注意的例外是 `YourModel.collection` 仍然会缓冲 命令。因此,`YourModel.collection.find()` 将**不会** 返回一个游标。 ## API 文档 [Mongoose API 文档](https://mongoosejs.com/docs/api/mongoose.html),使用 [dox](https://github.com/tj/dox) 和 [acquit](https://github.com/vkarpov15/acquit) 生成。 ## 相关项目 ### MongoDB 运行器 * [run-rs](https://www.npmjs.com/package/run-rs) * [mongodb-memory-server](https://www.npmjs.com/package/mongodb-memory-server) * [mongodb-topology-manager](https://www.npmjs.com/package/mongodb-topology-manager) ### 非官方 CLI * [mongoosejs-cli](https://www.npmjs.com/package/mongoosejs-cli) ### 数据填充 * [dookie](https://www.npmjs.com/package/dookie) * [seedgoose](https://www.npmjs.com/package/seedgoose) * [mongoose-data-seed](https://www.npmjs.com/package/mongoose-data-seed) ### Express Session 存储 * [connect-mongodb-session](https://www.npmjs.com/package/connect-mongodb-session) * [connect-mongo](https://www.npmjs.com/package/connect-mongo) ## 许可证 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.
标签:Bun, CMS安全, Deno, GNU通用公共许可证, JavaScript, MITM代理, MongoDB, Mongoose, Node.js, npm, ODM, pnpm, Yarn, 中间件, 包管理器, 后端开发, 对象建模, 对象文档映射, 异步环境, 数据可视化, 数据库, 数据验证, 模型定义, 统一API