介绍
Mongoose 是一个流行的 Node.js 的 ORM(对象关系映射)框架。它提供了非常方便的方式去定义和操作 MongoDB 的数据文档,支持查询,更新,删除等操作。其中, populate 功能可以实现深度获取数据库数据的相关联数据。本文将介绍如何使用 Mongoose 实现深度 populate,包含完整代码和详细讲解。
准备工作
在开始使用 Mongoose 的深度 populate 功能之前,需要先设置 MongoDB 连接。如果你还没有安装 MongoDB,可以访问 MongoDB 官网 安装。在安装好 MongoDB 之后,你需要在本地启动 MongoDB 服务,并创建一个数据库和一个用户。
在启动 MongoDB 后,你需要在命令行中输入以下命令创建一个数据库和一个用户:
$ mongo > use test > db.createUser({user: 'test', pwd: '123456', roles: [{role: 'readWrite', db: 'test'}]})
这里我们创建了一个名为 test 的数据库,并为 test 用户赋予了读写权限。
接下来,你需要安装 Mongoose 和 lodash 模块。你可以使用 npm 安装这两个模块。
$ npm install mongoose lodash
创建数据模型
为了实现深度 populate,我们需要定义几个数据模型。这里我们定义了 Book、Author、Publisher 三个模型,它们之间存在多对多和一对多的关系。
- Book 模型:
const bookSchema = new mongoose.Schema({ title: { type: String, required: true }, author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' }, publishers: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Publisher' }], }); const Book = mongoose.model('Book', bookSchema);
- Author 模型:
const authorSchema = new mongoose.Schema({ name: { type: String, required: true }, books: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }], }); const Author = mongoose.model('Author', authorSchema);
- Publisher 模型:
const publisherSchema = new mongoose.Schema({ name: { type: String, required: true }, books: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }], }); const Publisher = mongoose.model('Publisher', publisherSchema);
这里只定义了模型的 schema,我们还需要在代码中连接到 MongoDB 并使用模型。完整的代码如下:
const mongoose = require('mongoose'); const _ = require('lodash'); // 连接到 MongoDB mongoose.connect('mongodb://test:123456@localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true, }); // 定义 Book 模型 const bookSchema = new mongoose.Schema({ title: { type: String, required: true }, author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' }, publishers: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Publisher' }], }); const Book = mongoose.model('Book', bookSchema); // 定义 Author 模型 const authorSchema = new mongoose.Schema({ name: { type: String, required: true }, books: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }], }); const Author = mongoose.model('Author', authorSchema); // 定义 Publisher 模型 const publisherSchema = new mongoose.Schema({ name: { type: String, required: true }, books: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }], }); const Publisher = mongoose.model('Publisher', publisherSchema);
创建数据
我们需要先创建一些数据,以便进行深度 populate 的实验。这里我们创建两个作者,两个出版社,和两本书,它们之间存在多对多和一对多的关系。
// 创建作者和出版社 const author1 = await Author.create({ name: 'Tom' }); const author2 = await Author.create({ name: 'Jerry' }); const publisher1 = await Publisher.create({ name: 'Penguin' }); const publisher2 = await Publisher.create({ name: 'Oxford' }); // 创建书籍 const book1 = await Book.create({ title: 'Book1', author: author1._id, publishers: [publisher1._id, publisher2._id], }); const book2 = await Book.create({ title: 'Book2', author: author2._id, publishers: [publisher1._id], }); // 更新作者和出版社的书籍列表 await Author.updateOne({ _id: author1._id }, { $push: { books: book1._id } }); await Author.updateOne({ _id: author2._id }, { $push: { books: book2._id } }); await Publisher.updateOne( { _id: publisher1._id }, { $push: { books: book1._id, books: book2._id } } ); await Publisher.updateOne({ _id: publisher2._id }, { $push: { books: book1._id } });
这段代码先创建了两个作者和两个出版社,然后创建了两本书,并将它们关联到相应的模型中。
注意,当创建多对多关系时,需要使用数组类型。在这个例子中,我们使用了以下代码来将书籍与出版社相关联。
await Publisher.updateOne( { _id: publisher1._id }, { $push: { books: book1._id, books: book2._id } } );
这里我们在 books 数组中添加了两个 ObjectId,分别对应 book1 和 book2 的 id。
当创建完数据后,我们就可以进行深度 populate 的实验了。
深度 populate 实现
深度 populate 可以让我们在查询 Mongoose 数据库时,一次性获取多层嵌套的相关联数据。在使用 populate 函数获取数据时,可以设置 options 来实现深度 populate。
const options = { path: 'author', populate: { path: 'books', populate: { path: 'publishers', }, }, };
在 options 中的每个 path 属性都表示一个需要 populate 的字段。这里我们定义了深度为 2 的 path 链,分别对应 Book 模型中的 author、Publisher 模型中的 books 和 Book 模型中的 publishers。
接下来,我们使用 Mongoose 提供的 populate 方法获取数据。
const books = await Book.find().populate(options); console.log(JSON.stringify(books, null, 2));
这里我们获取了 Book 模型下的所有数据,并使用 options 参数采用深度 populate 的方式获取相关联数据。调用 populate 方法获取数据后,我们使用 JSON.stringify 方法将其输出到控制台。
完整代码如下:
const mongoose = require('mongoose'); const _ = require('lodash'); // 连接到 MongoDB mongoose.connect('mongodb://test:123456@localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true, }); // 定义 Book 模型 const bookSchema = new mongoose.Schema({ title: { type: String, required: true }, author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' }, publishers: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Publisher' }], }); const Book = mongoose.model('Book', bookSchema); // 定义 Author 模型 const authorSchema = new mongoose.Schema({ name: { type: String, required: true }, books: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }], }); const Author = mongoose.model('Author', authorSchema); // 定义 Publisher 模型 const publisherSchema = new mongoose.Schema({ name: { type: String, required: true }, books: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Book' }], }); const Publisher = mongoose.model('Publisher', publisherSchema); (async () => { // 创建作者和出版社 const author1 = await Author.create({ name: 'Tom' }); const author2 = await Author.create({ name: 'Jerry' }); const publisher1 = await Publisher.create({ name: 'Penguin' }); const publisher2 = await Publisher.create({ name: 'Oxford' }); // 创建书籍 const book1 = await Book.create({ title: 'Book1', author: author1._id, publishers: [publisher1._id, publisher2._id], }); const book2 = await Book.create({ title: 'Book2', author: author2._id, publishers: [publisher1._id], }); // 更新作者和出版社的书籍列表 await Author.updateOne({ _id: author1._id }, { $push: { books: book1._id } }); await Author.updateOne({ _id: author2._id }, { $push: { books: book2._id } }); await Publisher.updateOne( { _id: publisher1._id }, { $push: { books: book1._id, books: book2._id } } ); await Publisher.updateOne({ _id: publisher2._id }, { $push: { books: book1._id } }); // 深度 populate const options = { path: 'author', populate: { path: 'books', populate: { path: 'publishers', }, }, }; const books = await Book.find().populate(options); console.log(JSON.stringify(books, null, 2)); // 关闭连接 mongoose.disconnect(); })();
总结
在本文中,我们介绍了如何使用 Mongoose 实现深度 populate。我们通过定义数据模型,创建数据,以及使用 Mongoose 提供的 populate 方法实现了深度获取相关联数据的功能。对于需要大量嵌套查询的数据场景,通过 Mongoose 提供的深度 populate 功能,可以大大提高查询效率。希望本文对你学习和使用 Mongoose 有所帮助。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b0eca3add4f0e0ffa43c17