Overview概述
Mongoose is an Object Data Modeling (ODM) library for MongoDB. You can use Mongoose to help with data modeling, schema enforcement, model validation, and general data manipulation. Because MongoDB has a flexible data model that allows you to alter and update databases in the future, there aren't rigid schemas. Mongoose是MongoDB的对象数据建模(ODM)库。您可以使用Mongoose来帮助进行数据建模、模式实施、模型验证和一般数据操作。因为MongoDB有一个灵活的数据模型,允许您在未来更改和更新数据库,所以没有严格的模式。However, Mongoose enforces a semi-rigid schema from the beginning, so you must define a schema and model.然而,Mongoose从一开始就强制执行半刚性模式,因此您必须定义一个模式和模型。
Schemas模式
A schema defines the structure of your collection documents. A Mongoose schema maps directly to a MongoDB collection.模式定义了集合文档的结构。Mongoose模式直接映射到MongoDB集合。
The following example creates a new Schema named 以下示例创建了一个名为blog:blog的新模式:
const blog = new Schema({
title: String,
slug: String,
published: Boolean,
author: String,
content: String,
tags: [String],
comments: [{
user: String,
content: String,
votes: Number
}]
}, {
timestamps: true
});
When you create a schema, you must define each field and its data types. The following types are permitted:创建模式时,必须定义每个字段及其数据类型。允许使用以下类型:
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- ObjectId
- Array
- Int32
- Decimal128
- Double
- Map
Models模型
Models take your schema and apply it to each document in its collection. Models are responsible for all document interactions such as create, read, update, and delete (CRUD) operations.模型采用您的模式并将其应用于其集合中的每个文档。模型负责所有文档交互,如创建、读取、更新和删除(CRUD)操作。
Tip
The first argument you pass to the model is the singular form of your collection name. Mongoose automatically changes this to the plural form, transforms it to lowercase, and uses that for the database collection name.传递给模型的第一个参数是集合名称的单数形式。Mongoose会自动将其更改为复数形式,将其转换为小写,并将其用作数据库集合名称。
The following example shows how to declare a model named 以下示例显示了如何声明一个名为Blog that uses the blog schema:Blog的模型,该模型使用blog模式:
const Blog = mongoose.model('Blog', blog);
In the preceding example, 在前面的示例中,Blog translates to the blogs collection in MongoDB.Blog转换为MongoDB中的blogs集合。
Tutorial教程
In this tutorial, you will perform the following actions:在本教程中,您将执行以下操作:
Set up your environment to use Mongoose设置您的环境以使用MongooseConnect to MongoDB连接到MongoDBCreate a Mongoose schema and model创建Mongoose模式和模型Insert, update, find, and delete data插入、更新、查找和删除数据Project document fields项目文档字段Validate your data验证您的数据Use multiple schemas and middleware使用多种模式和中间件
Verify the prerequisites验证先决条件
Before you begin this tutorial, ensure you have the following components prepared:在开始本教程之前,请确保您已准备好以下组件:
An MongoDB Atlas account with a configured cluster. To view instructions, see the MongoDB Get Started guide.一个配置了集群的MongoDB Atlas帐户。要查看说明,请参阅MongoDB入门指南。- Node.js
v16.20.1 or later.v16.20.1或更高版本。
Set up your environment设置您的环境
This tutorial uses nodemon to run the code locally. Run the following commands in your terminal to initialize your project and install the necessary dependencies:本教程使用nodemon在本地运行代码。在终端中运行以下命令以初始化项目并安装必要的依赖项:
mkdir mongodb-mongoose
cd mongodb-mongoose
npm init -y
npm i mongoose
npm i -D nodemon
Open your project in your preferred code editor. This tutorial uses ES Modules instead of CommonJS. You must add the 在您喜欢的代码编辑器中打开您的项目。本教程使用ES模块而不是CommonJS。您必须添加module type to use ES Modules. Go to the package.json file and add the following code:module类型才能使用ES模块。转到package.json文件并添加以下代码:
...
"scripts": {
"dev": "nodemon index.js"
},
"type": "module",
...
Start your application with 通过运行以下命令,使用nodemon by running the following command:nodemon启动应用程序:
npm run dev
Note
When you use nodemon, the code runs every time you save a file.当您使用nodemon时,每次保存文件时都会运行代码。
Connect to MongoDB连接到MongoDB
In the root level of your project, create a file named 在项目的根级别,创建一个名为index.js and add the following code to the top of the file:index.js的文件,并将以下代码添加到文件顶部:
import mongoose from 'mongoose';
mongoose.connect("<connection string>")
Replace the 将<connection string> placeholder with your MongoDB Atlas connection string. For more information on how to find your connection string, see the Connect to Your Cluster tutorial in the Atlas documentation.<connection-string>占位符替换为MongoDB Atlas连接字符串。有关如何查找连接字符串的更多信息,请参阅Atlas文档中的“连接到集群”教程。
Create a schema and a model创建模式和模型
Before you start adding and updating data in MongoDB, you must create a schema and model.在MongoDB中开始添加和更新数据之前,您必须创建一个模式和模型。
With Mongoose, you create a schema model file for each schema that is needed. First, create a folder called 使用Mongoose,您可以为所需的每个模式创建一个模式模型文件。首先,创建一个名为model to put all your schema files in, then create your first schema file called Blog.js. Open this file and add the following code:model的文件夹来存放所有模式文件,然后创建第一个名为Blog.js的模式文件。打开此文件并添加以下代码:
import mongoose from 'mongoose';
const { Schema, model } = mongoose;
const blogSchema = new Schema({
title: String,
slug: String,
published: Boolean,
author: String,
content: String,
tags: [String],
comments: [{
user: String,
content: String,
votes: Number
}]
}, {
timestamps: true
});
const Blog = model('Blog', blogSchema);
export default Blog;
This schema enables a 此模式启用了timestamps option, which adds mongoose-manged createdAt and updatedAt fields to the schema that are updated automatically. timestamps(时间戳)选项,该选项将mongose管理的createdAt和updatedAt字段添加到自动更新的模式中。For more information, see the Timestamps page in the Mongoose documentation.有关更多信息,请参阅Mongoose文档中的时间戳页面。
Perform CRUD operations执行CRUD操作
You now have your first model and schema set up, and you can start inserting data into the database. The following sections show you how to perform CRUD operations using Mongoose.现在,您已经设置了第一个模型和模式,可以开始将数据插入数据库。以下部分将向您展示如何使用Mongoose执行CRUD操作。
Insert Data插入数据
Go to 转到index.js and add the following import statement to the top of your file:index.js并将以下import语句添加到文件顶部:
import Blog from './model/Blog.js';
Add the following code below the line that contains your connection string:在包含连接字符串的行下方添加以下代码:
// Creates a new blog post and inserts it into database
const article = await Blog.create({
title: 'Awesome Post!',
slug: 'awesome-post',
published: true,
content: 'This is the best post ever',
tags: ['featured', 'announcement'],
});
console.log('Created article:', article);
The preceding code uses the Mongoose 前面的代码使用Mongoose create() method to instantiate the object representing a blog article, and then saves it to the database. The returned document logs to the console, including its _id. Take note of this _id for use in future steps.create()方法实例化表示博客文章的对象,然后将其保存到数据库中。返回的文档记录到控制台,包括其_id。记下这个_id,以便在以后的步骤中使用。
Update Data更新数据
To update data, you can directly edit the local object with Mongoose. Then, you can use the 要更新数据,您可以直接使用Mongoose编辑本地对象。然后,您可以使用save() method to write the update to the database.save()方法将更新写入数据库。
Add the following code to update the article you inserted in the previous section:添加以下代码以更新您在上一节中插入的文章:
// Updates the title of the article
article.title = "The Most Awesomest Post!!";
await article.save();
console.log('Updated Article:', article);
Updated Article: {
title: 'The Most Awesomest Post!!',
slug: 'awesome-post',
published: true,
content: 'This is the best post ever',
tags: [ 'featured', 'announcement' ],
_id: new ObjectId('...'),
comments: [],
__v: 0
}Find Data查找数据
To find a specific document, you can use the Mongoose 要查找特定文档,可以使用Mongoose findById() method to query for a document by specifying its _id.findById()方法通过指定文档的_id来查询文档。
Add following code to your 在index.js file to find a specific article by its _id:index.js文件中添加以下代码,根据_id查找特定文章:
// Finds the article by its ID. Replace <object id> with the objectId of the article.按文章的ID查找文章。将<object id>替换为文章的objectId。
const articleFound = await Blog.findById("<object id>").exec();
console.log('Found Article by ID:', articleFound);
Found Article by ID: {
_id: new ObjectId('68261c9dae39e390341c367c'),
title: 'The Most Awesomest Post!!',
slug: 'awesome-post',
published: true,
content: 'This is the best post ever',
tags: [ 'featured', 'announcement' ],
comments: [],
__v: 0
}
Note
By default, Mongoose queries return thenables, which are objects with some properties of a JavaScript Promise. You can append the 默认情况下,Mongoose查询返回thenables,它们是具有JavaScript Promise某些属性的对象。您可以将exec() method to a query to receive a true JavaScript Promise. exec()方法附加到查询中以接收真正的JavaScript Promise。To learn more about working with promises in Mongoose, see the Promises guide in the Mongoose documentation.要了解有关在Mongoose中使用promises的更多信息,请参阅Mongoose文档中的promises指南。
Specify Document Fields指定文档字段
You can use Mongoose to project only the fields that you need. The following code specifies to only project the 您可以使用Mongoose仅投影所需的字段。以下代码指定仅投影title, slug, and content fields.title、slug和content字段。
Add the following code to your 将以下代码添加到index.js file, replacing the <object id> placeholder with the ObjectId value for the document that you inserted previously:index.js文件中,用之前插入的文档的ObjectId值替换<object id>占位符:
// Finds the article by its ID and projects only the title, slug, and content fields.按文章的ID查找文章,并仅投影标题、slug和内容字段。
// Replace <object id> with the objectId of the article.
const articleProject = await Blog.findById("<object id>", "title slug content").exec();
console.log('Projected Article:', articleProject);
Projected Article: {
_id: new ObjectId('...'),
title: 'The Most Awesomest Post!!',
slug: 'awesome-post',
content: 'This is the best post ever'
}Delete Data删除数据
Mongoose uses the Mongoose使用deleteOne() and deleteMany() methods to delete data from a collection. You can specify the field of the document you want to delete and pass that field to the method that you choose.deleteOne()和deleteMany()方法从集合中删除数据。您可以指定要删除的文档的字段,并将该字段传递给您选择的方法。
Add the following code to your index.js file to delete one article from the database:将以下代码添加到indexjs文件中,以从数据库中删除一篇文章:
// Deletes one article with the slug "awesome-post".删除一篇带有“真棒帖子”的文章。
const blogOne = await Blog.deleteOne({ slug: "awesome-post" });
console.log('Deleted One Blog:', blogOne);
Deleted One Blog: { acknowledged: true, deletedCount: 1 }
To delete multiple articles, you can add the following code:要删除多篇文章,可以添加以下代码:
// Deletes all articles with the slug "awesome-post".删除所有带有“真棒帖子”字样的文章。
const blogMany = await Blog.deleteMany({ slug: "awesome-post" });
console.log('Deleted Many Blogs:', blogMany);
Deleted Many Blogs: { acknowledged: true, deletedCount: 4 }Validate your data验证您的数据
The articles inserted in the previous steps do not contain the 在前面的步骤中插入的文章不包含author, dates, or comments fields, even though these fields are included in the schema. This is because although you defined the structure of your document, you have not defined which fields are required. Any field that is not defined as required can be omitted.author(作者)、dates(日期)或comments(评论)字段,即使这些字段包含在架构中。这是因为,虽然您定义了文档的结构,但尚未定义哪些字段是必需的。任何未按要求定义的字段都可以省略。
In Mongoose, when you include validation on a field, you must pass an object as its value.在Mongoose中,当您在字段上包含验证时,您必须传递一个对象作为其值。
Note
Validators automatically run on the 验证器会自动在create() and save() methods. create()和save()方法上运行。You can specify them to run them on update methods, such as 您可以通过将update() and updateOne() by setting the runValidators option to true. runValidators选项设置为true来指定它们在更新方法上运行,例如update()和updateOne()。For more information about validators, see the Validation page in the Mongoose documentation.有关验证器的更多信息,请参阅Mongoose文档中的验证页面。
You can use several validation methods with Mongoose. For example, you can set 您可以在Mongoose中使用多种验证方法。例如,您可以在任何需要的字段上将required to true on any fields that you want to require. You can also validate the type and the formatting. required设置为true。您还可以验证类型和格式。In the following code, the 在以下代码中,slug field is defined as a string with a minLength of 4. This means that providing a slug with fewer than 4 characters will result in a ValidationError.slug字段被定义为minLength为4的字符串。这意味着提供少于4个字符的slug将导致ValidationError。
To add data validation and define these requirements, update the schema in 要添加数据验证并定义这些要求,请更新Blog.js as shown in the following example:Blog.js中的模式,如下例所示:
const blogSchema = new Schema({
title: {
type: String,
required: true,
},
slug: {
type: String,
required: true,
minLength: 4,
},
published: {
type: Boolean,
default: false,
},
author: {
type: String,
required: true,
},
content: String,
tags: [String],
comments: [{
user: String,
content: String,
votes: Number
}]
}, {
timestamps: true
});
After adding this validation, your application will crash. Add an 添加此验证后,您的应用程序将崩溃。在author field to the create() call in your index.js file to meet the new validation requirement:index.js文件的create()调用中添加author(作者)字段,以满足新的验证要求:
// Creates a new blog post and inserts it into database创建新的博客文章并将其插入数据库
const article = await Blog.create({
title: 'Awesome Post!',
slug: 'awesome-post',
published: true,
author: 'A.B. Cee',
content: 'This is the best post ever',
tags: ['featured', 'announcement'],
});
Tip
When you use schemas with Mongoose, 当您在Mongoose中使用模式时,value: String is the same as value: {type: String}.value:String与value:{type:String}相同。
For more information, see the Validation page in the Mongoose documentation.有关更多信息,请参阅Mongoose文档中的验证页面。
Introduce multiple schemas引入多种模式
Next, you can add more complexity to your 接下来,您可以通过创建另一个模式并将其嵌套在博客模式中来增加author field by creating a another schema, and nesting it in the blog schema.author字段的复杂性。
In the 在model folder, create a new file named User.js. Add the following code to this file:model文件夹中,创建一个名为User.js的新文件。将以下代码添加到此文件中:
import mongoose from 'mongoose';
const {Schema, model} = mongoose;
const userSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
minLength: 10,
required: true,
lowercase: true
},
});
const User = model('User', userSchema);
export default User;
To use your new User model to define the 要使用新的用户模型定义博客模式中的author field in the blog schema, update the Blog.js file with the following changes:author字段,请使用以下更改更新Blog.js文件:
Add将SchemaTypesto the list of properties extracted from the Mongoose library.SchemaTypes添加到从Mongoose库提取的属性列表中。Change the将authorfieldtypetoSchemaTypes.ObjectIdand add a reference (ref) to the'User'model.author字段类型更改为SchemaTypes.ObjectId,并向'User'模型添加引用(ref)。
The following code shows these updates:以下代码显示了这些更新:
const { Schema, SchemaTypes, model } = mongoose;
... // Inside Schema block:架构块内部:
author: {
type: SchemaTypes.ObjectId,
ref: 'User',
required: true,
},
...
You can reuse the same 您可以通过更改User model for the comment.user field by changing the blogSchema definition:blogSchema定义为comment.user字段重用相同的User模型:
... // Inside Schema block:架构块内部:
comments: [{
user: {
type: SchemaTypes.ObjectId,
ref: 'User',
required: true,
},
...
To use the new user model in your application, go to the 要在应用程序中使用新的用户模型,请转到index.js file. Add the following code to the top of the file to import the user model:index.js文件。将以下代码添加到文件顶部以导入用户模型:
import User from './model/User.js';
Because you added field validation to the blog schema, the previous code to insert, update, and delete blogs, and to specify fields to project, won't pass the validation and the application will error.因为您在博客架构中添加了字段验证,所以之前插入、更新和删除博客以及指定要投影的字段的代码将无法通过验证,应用程序将出错。
Create a new user by adding the following 通过添加以下create() call:Create()调用创建新用户:
// Create a new user创建新用户
const user = await User.create({
name: 'Jess Garica',
email: 'jgarcia@email.com',
});
Update the existing 使用以下代码更新现有的create() call with the following code to create a new article that uses the new user as the author, as shown in the following code:create()调用,以创建一篇使用新用户作为作者的新文章,如以下代码所示:
// Creates a new blog post that references the user as the author创建一篇引用用户作为作者的新博客文章
const articleAuthor = await Blog.create({
title: 'Awesome Post!',
slug: 'Awesome-Post',
author: user._id,
content: 'This is the best post ever',
tags: ['featured', 'announcement'],
});
console.log('Article with Author:', articleAuthor);
Article with Author: {
title: 'Awesome Post!',
slug: 'awesome-post',
published: false,
author: new ObjectId('...'),
content: 'This is the best post ever',
tags: [ 'featured', 'announcement' ],
_id: new ObjectId('...'),
createdAt: 2025-05-15T18:05:23.780Z,
comments: [],
__v: 0
}
The preceding code adds a 前面的代码在MongoDB数据库中添加了一个users collection with the blogs collection in the MongoDB database. This code adds the required author field and sets its value to the user._id.users集合和blogs集合。此代码添加了必需的author 字段,并将其值设置为user._id。
To add the values of the 要将name and email fields to the author field for the article, you can append the Mongoose populate() method to your Blog query. The populate() method will perform a second query for the User document referenced by user._id.name和email字段的值添加到文章的author字段中,您可以将Mongoose populate()方法附加到您的博客查询中。populate()方法将对用户引用的User文档执行第二次查询。_id。
Add the following code to 将以下代码添加到index.js to populate this data:index.js中以填充此数据:
// Populates the author field with user data用用户数据填充作者字段
const articlePopulate = await Blog.findOne({ title: "Awesome Post!" }).populate("author");
console.log('Article Populated:', articlePopulate);
Article Populated: {
_id: new ObjectId('...'),
title: 'Awesome Post!',
slug: 'awesome-post',
published: false,
author: {
_id: new ObjectId('...'),
name: 'Jess Garica',
email: 'jgarcia@email.com',
__v: 0
},
content: 'This is the best post ever',
tags: [ 'featured', 'announcement' ],
createdAt: 2025-05-15T18:04:28.590Z,
comments: [],
__v: 0
}
For more information, see the Document.populate() page of the Mongoose API documentation.有关更多信息,请参阅Mongoose API文档的Document.populate()页面。
Add middleware添加中间件
In Mongoose, middleware are functions that run before, or during, the execution of asynchronous functions at the schema level.在Mongoose中,中间件是在模式级别执行异步函数之前或期间运行的函数。
One example of middleware is a function that validates the 中间件的一个例子是在保存或更新之前验证email field of a User instance before saving or updating.User实例的email字段的函数。
This example uses the 此示例使用validator package. You can install the validator package by running the following command:validator包。您可以通过运行以下命令安装validator包:
npm install validator
To add this middleware function, add the following code to the 要添加此中间件函数,请将以下代码添加到userSchema declaration in your User.js file:User.js文件中的userSchema声明中:
import validator from 'validator';
userSchema.pre('save', function (next) {
const user = this;
// Normalize email规范电子邮件
if (user.email) {
user.email = user.email.trim().toLowerCase();
}
// Validate email format验证电子邮件格式
if (!validator.isEmail(user.email)) {
return next(new Error('Invalid email format'));
}
next();
});
To see the effect of this function, modify the 要查看此函数的效果,请修改user.email field in your index.js file to make it an invalid email address:index.js文件中的user.email字段,使其成为无效的电子邮件地址:
const user = await User.create({
name: 'Jess Garica',
email: 'jgarciaemail.com',
});
Error: Invalid email format
If you correct the email address, you can see that the error is not thrown.如果你更正了电子邮件地址,你可以看到没有抛出错误。
Besides the 除了pre() middleware function, Mongoose also offers a post() middleware function. For more information about middleware, see the Middleware page in the Mongoose documentation.pre()中间件函数外,Mongoose还提供了post()中间件功能。有关中间件的更多信息,请参阅Mongoose文档中的中间件页面。
Next Steps后续步骤
You now have a sample project that uses Mongoose to perform CRUD operations on a MongoDB collection. From here, you can choose to build on this project with more complex queries or document validation. The following sections includes some examples of Mongoose features that you might use to in your application.现在,您有一个使用Mongoose对MongoDB集合执行CRUD操作的示例项目。从这里,您可以选择使用更复杂的查询或文档验证来构建此项目。以下部分包括您可能在应用程序中使用的Mongoose功能的一些示例。
Mongoose Custom SettersMongoose定制套装
Custom setters modify your data when it is saved, and can be implemented similar to validators. Mongoose provides the following custom setters:自定义设置程序在保存数据时对其进行修改,并且可以类似于验证器来实现。Mongoose提供以下自定义设置程序:
lowercaseuppercasetrim
The following example lowercases the characters in the 以下示例降低了blog.slug field:blog.slug字段中的字符:
const blogSchema = new Schema({
...
slug: {
type: String,
required: true,
minLength: 4,
lowercase: true,
},
...
});
For more information, see the SchemaStringOptions page in the Mongoose API documentation.有关更多信息,请参阅Mongoose API文档中的SchemaStringOptions页面。
Helper Methods帮助方法
Mongoose includes several helper methods that are abstracted from regular MongoDB methods. In this section, you can find examples of some of these methods. These methods are not used specifically in this tutorial, but they are helpful to reference when getting started with Mongoose.Mongoose包括几个从常规MongoDB方法中抽象出来的辅助方法。在本节中,您可以找到其中一些方法的示例。本教程中没有具体使用这些方法,但在开始使用Mongoose时可以参考它们。
exists()
The exists() method returns either null or the first document that matches the provided query. The following is an example of matching an article based on the author field:exists()方法返回null或与提供的查询匹配的第一个文档。以下是一个基于作者字段匹配文章的示例:
const blog = await Blog.exists({ author: 'Jess Garcia' });
console.log(blog);
For more information, see the Model.exists() section of the Mongoose API documentation.有关更多信息,请参阅Mongoose API文档的Model.exists()部分。
where()
The where() method allows you to chain and build complex queries.where()方法允许您链接和构建复杂的查询。
The following is an example of performing a find operation by using 以下是一个使用findOne() with a plain query object and the equivalent query with the where() method:findOne()和一个普通查询对象执行查找操作的示例,以及使用where()方法执行等效查询的示例:
const blogFind = await Blog.findOne({ author: "Jess Garcia" });
console.log(blogFind);
const blogWhere = await Blog.findOne().where("author").equals("Jess Garcia");
console.log(blogWhere);
In this implementation, the 在这个实现中,where() implementation starts with a findOne() which tells Mongoose to treat it as a findOne() query. This is important because if you use where() on its own (Blog.where(...)), Mongoose implicitly treats it as a find() operation.where()实现从一个findOne()开始,它告诉Mongoose将其视为一个findOne()查询。这很重要,因为如果你单独使用where()(Blog.where(...)),Mongoose会隐式地将其视为find()操作。
Generally, the 通常,where() method is used for complex queries involving dynamic query building or multiple comparators, or when using this method improves readability. There is no performance difference between using the where() method or a plain object query.where()方法用于涉及动态查询构建或多个比较器的复杂查询,或者在使用此方法时提高可读性。使用where()方法和普通对象查询之间没有性能差异。
To include projection when using the 要在使用where() method, chain the select() method after your query, as shown in the following example:where()方法时包含投影,请在查询后链接select()方法,如下例所示:
const blog = await Blog.findOne().where("author").equals("Jess Garcia").select("title author");
console.log(blog);
For more information, see the following sections of the Mongoose API documentation:有关更多信息,请参阅Mongoose API文档的以下部分:
Additional Resources其他资源
To learn more about using Mongoose with MongoDB, see the Mongoose documentation.要了解有关在MongoDB中使用Mongoose的更多信息,请参阅Mongoose文档。
To find support or to contribute to the MongoDB community, see the MongoDB Developer Community page.要寻求支持或为MongoDB社区做出贡献,请参阅MongoDB开发人员社区页面。