Mongoose 是基于 Node.js 的 MongoDB 驱动程序,它提供了一套有用的工具和函数,使得在 Node.js 应用中使用 MongoDB 数据库变得更加容易。
在实际项目开发中,经常会涉及到两个或多个集合的联表查询,这时候就需要使用 MongoDB 的聚合管道操作符,其中 $lookup 操作符是我们经常使用的一个。
$lookup 操作符
$lookup 操作符主要用于在一个集合中添加其他集合中的文档数据。它可以用来创建一个新字段,这个新字段可以包含所有满足条件的文档(或者部分文档),或者是单纯的把两个相关文档合并成一个文档。
$lookup 操作符的格式如下:
-- -------------------- ---- ------- - -------- - ----- ----------- -- ------ ----------- ------ ---- --- ----- ----------- ------------- ------ ---- --- --------- -- --- ------ ------------ --- ------- ----- ------ - -
其中,from
参数表示要联接的集合名称,localField
和 foreignField
分别是当前集合和目标集合之间对应的字段,as
是输出的结果字段名称。
举个例子,如果我们有两个集合分别是 users 和 orders,它们之间的关系是 users 包含一个 orderIds 数组,数组中的元素是 orders 集合中的 _id,表示这个用户对应的订单。那么我们就可以使用 $lookup 操作符来完成这个查询,具体代码如下:
-- -------------------- ---- ------- -------------------- - -------- - ----- --------- ----------- ----------- ------------- ------ --- -------- - - --
上面的代码中,我们使用了 $lookup 操作符来将 orders 集合中与当前用户相关的订单附加到这个用户文档中的 orders 字段中。
利用 Mongoose 进行联表查询
在项目中,我们通常使用 Mongoose 来操作 MongoDB 数据库。Mongoose 提供了很多方法来执行聚合管道,其中 aggregate() 方法是用来构造聚合管道的入口。
在使用 $lookup 操作符时,我们可以直接在聚合管道中使用该操作符,具体代码如下:
-- -------------------- ---- ------- ---------------- - -------- - ----- --------- -- ------ ----------- ----------- -- --------- ------------- ------ -- ----------- --- -------- -- -------- - - --
以上代码是以 User 为主表(即 users 集合),orders 为从表(即 orders 集合),将 orders 数据通过 user 的 orderIds 与 user 关联起来,最终输出的结果就是将 orders 的信息添加到 user 的 orders 字段中。
案例分析
下面,我们来看一组具体的样例数据,其中 students 和 teachers 分别表示学生和老师的数据集合。
students 集合数据如下:
[ { _id: ObjectId('60fe1c09bae8c32a88b36a31'), name: 'Tom', age: 18, teacherId: ObjectId('60fe1be8bae8c32a88b36a2f') }, { _id: ObjectId('60fe1c3cbae8c32a88b36a32'), name: 'Jerry', age: 19, teacherId: ObjectId('60fe1be8bae8c32a88b36a2f') }, { _id: ObjectId('60fe1c4cbae8c32a88b36a33'), name: 'Sandy', age: 20, teacherId: ObjectId('60fe1bfebae8c32a88b36a30') }, ]
teachers 集合数据如下:
[ { _id: ObjectId('60fe1be8bae8c32a88b36a2f'), name: 'Mr. Zhang', title: 'Math teacher' }, { _id: ObjectId('60fe1bfebae8c32a88b36a30'), name: 'Ms. Li', title: 'English teacher' }, ]
上面的数据表示,Tom 和 Jerry 的导师是 Mr. Zhang,而 Sandy 的导师是 Ms. Li。我们现在要通过 students 集合的 teacherId 字段来关联 teachers 集合的数据,最终输出的结果需要包含所有学生的信息和对应的老师信息。
首先,我们需要定义两个 Schema,分别对应学生和老师的数据结构:
-- -------------------- ---- ------- -- -- ------ ----- ------------- - --- ----------------- ----- ------- ---- ------- ---------- ------------------------------ -- -- -- ------ ----- ------------- - --- ----------------- ----- ------- ------ ------ --
接着,我们需要创建两个 Mongoose 模型,定义 students 和 teachers 的数据集合:
const Student = mongoose.model('Student', studentSchema, 'students') const Teacher = mongoose.model('Teacher', teacherSchema, 'teachers')
最后,我们可以使用 Mongoose 的 aggregate() 方法来完成我们的查询任务:
-- -------------------- ---- ------- ------------------- - -------- - ----- ----------- ----------- ------------ ------------- ------ --- ------------- - - -------------- -- - ------------------- --
通过以上代码,我们将 teachers 数据连接到了 students 数据集合中,最终的查询结果如下所示:
-- -------------------- ---- ------- - - ------ --------------------------- ------- ------ ------ --- ------------ --------------------------- -------------- - - ------ --------------------------- ------- ---- ------- -------- ----- -------- - - -- - ------ --------------------------- ------- -------- ------ --- ------------ --------------------------- -------------- - - ------ --------------------------- ------- ---- ------- -------- ----- -------- - - -- - ------ --------------------------- ------- -------- ------ --- ------------ --------------------------- -------------- - - ------ --------------------------- ------- ---- ---- -------- -------- -------- - - - -
从上面的结果中,我们可以看到,每个学生的信息都被包含在了结果中,并且它们的教师信息也被添加到了 teacherInfo 字段中。
总结
$lookup 操作符是 MongoDB 中非常常用的聚合管道操作符,它可以帮助我们连接不同的 MongoDB 集合,并将这些集合的信息组合在一起。利用 Mongoose,我们可以更加方便地进行联表查询,从而实现数据库数据的复杂关联分析。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/647c1aa5968c7c53b074884f