MongoDB 如何实现对合并后的文档进行筛选?
在 MongoDB 中,我们经常需要对合并后的文档进行筛选,以满足我们对数据的查询和业务需求。合并后的文档通常指的是在 $lookup 或 $graphLookup 操作中,将多个集合中的文档合并成一个文档。
本文将介绍 MongoDB 如何实现对合并后的文档进行筛选,并提供相关示例代码。
使用 $lookup 对多个集合进行合并
$lookup 是 MongoDB 中用于连接多个集合的操作符,它可以连接本地集合或外部集合,然后将这些文档进行合并。以下是 $lookup 的基本语法:
db.collection.aggregate([ { $lookup: { from: <collection>, localField: <field>, foreignField: <field from the documents of the "from" collection>, as: <output> } } ])
其中,参数说明如下:
- from:要连接的集合的名称。
- localField:输入文档中用于连接的字段。
- foreignField:要连接到的集合中用于连接的字段。
- as:输出的数组字段名称。
例如,我们有两个集合 orders 和 customers,它们的字段如下所示:
orders 集合
{ "_id": ObjectId("5f596db4931fae9457b42161"), "order_no": "20200912X001", "customer_id": ObjectId("5f596db4931fae9457b42160") }
customers 集合
{ "_id": ObjectId("5f596db4931fae9457b42160"), "customer_name": "Tom", "age": 30 }
我们可以使用以下 $lookup 操作将这两个集合中的文档进行连接:
db.orders.aggregate([ { $lookup: { from: "customers", localField: "customer_id", foreignField: "_id", as: "customer" } } ])
这个操作将 orders 中的每个文档都与 customers 中找到的具有相同 _id 值的文档进行连接,然后将连接后的文档存储在 customer 数组字段中。
连接后的文档如下所示:
{ "_id": ObjectId("5f596db4931fae9457b42161"), "order_no": "20200912X001", "customer_id": ObjectId("5f596db4931fae9457b42160"), "customer": [ { "_id": ObjectId("5f596db4931fae9457b42160"), "customer_name": "Tom", "age": 30 } ] }
筛选合并后的文档
在上面的操作中,我们已经将 orders 和 customers 两个集合中的文档进行了连接,得到了合并后的文档,并存储在了 customer 数组字段中。现在我们需要根据需求对合并后的文档进行筛选。
常用的筛选操作符有以下几个:
- $match:用于筛选合并后文档的内容。
- $unwind:用于展开合并后文档中的数组。
- $project:用于选择、重命名、新增或删除合并后文档的字段。
- $sort:用于对合并后文档进行排序。
- $limit:用于限制合并后文档的数量。
- $skip:用于跳过一定数量的合并后文档。
以下是这些操作符的详细说明:
$match 筛选器:
$match 筛选器在合并后的文档中进行匹配,以获取符合条件的文档。
例如,我们只需要找到姓“Smith”的客户订单,可以使用以下操作:
db.orders.aggregate([ { $lookup: { from: "customers", localField: "customer_id", foreignField: "_id", as: "customer" } }, { $unwind: "$customer" }, { $match: { "customer.customer_name": "Smith" } } ])
$unwind 操作符:
在文档中存在数组时,可使用 $unwind 可以展开数组,将数组中的每个元素与父级文档一起合并到新文档中。
例如,我们只需要找到顾客名字为“John”并展开其所有订单信息:
db.customers.aggregate([ { $lookup: { from: "orders", localField: "_id", foreignField: "customer_id", as: "orders_info" } }, { $unwind: "$orders_info" }, { $match: { "name": "John", "orders_info.order_no": { $regex: /^2020/ } } }, { $project: { "name": 1, "orders_info.order_no": 1, "_id": 0 } } ])
在这个操作中,我们首先使用 $lookup 操作将 customers 和 orders 两个集合中的文档进行连接,并将连接后的文档存储在 orders_info 数组字段中。
然后使用 $unwind 操作将 orders_info 数组展开。
接着使用 $match 操作筛选出 name 为“John”,并且订单号以“2020”开头的文档。
最后使用 $project 操作选择“name”和“orders_info.order_no”字段,并删除所有的 _id 字段。
$project 操作符:
$project 筛选器允许对文档进行选择、重命名、新增或删除字段。
例如,我们只需要获取“orders_info.order_no”和“customers.customer_name”字段,可以使用以下操作:
db.customers.aggregate([ { $lookup: { from: "orders", localField: "_id", foreignField: "customer_id", as: "orders_info" } }, { $unwind: "$orders_info" }, { $match: { "orders_info.order_no": { $regex: /^2020/ } } }, { $project: { "orders_info.order_no": 1, "customer_name": "$name", "_id": 0 } } ])
在这个操作中,我们首先使用 $lookup 操作将 customers 和 orders 两个集合中的文档进行连接,并将连接后的文档存储在 orders_info 数组字段中。
然后使用 $unwind 操作将 orders_info 数组展开。
接着使用 $match 操作筛选出订单号以“2020”开头的文档。
最后使用 $project 操作选择“orders_info.order_no”和“customers.customer_name”字段,并使用重命名操作符将“name”重命名为“customer_name”,并删除所有的 _id 字段。
$sort 操作符:
使用 $sort 操作符对合并后的文档进行排序。
例如,我们需要将所有订单按订单号升序排序:
db.orders.aggregate([ { $lookup: { from: "customers", localField: "customer_id", foreignField: "_id", as: "customer" } }, { $unwind: "$customer" }, { $sort : { "order_no": 1 } } ])
在这个操作中,我们首先使用 $lookup 操作将数据进行连接,然后使用 $unwind 操作展开 orders 和 customers 两个集合中的文档。
最后使用 $sort 操作按照订单号升序排序。
$limit 和 $skip 操作符:
$limit 和 $skip 筛选器可以用来控制查询结果的数量。
例如,我们只需要获取前 5 条订单:
db.orders.aggregate([ { $lookup: { from: "customers", localField: "customer_id", foreignField: "_id", as: "customer" } }, { $unwind: "$customer" }, { $sort : { "order_no": 1 } }, { $limit : 5 } ])
在这个操作中,我们首先使用 $lookup 操作将数据进行连接,然后使用 $unwind 操作展开 orders 和 customers 两个集合中的文档。
接着使用 $sort 操作按照订单号升序排序,然后使用 $limit 筛选器限制结果数量为 5。
总结
本文介绍了 MongoDB 如何实现对合并后的文档进行筛选。合并后的文档通常指的是在 $lookup 或 $graphLookup 操作中,将多个集合中的文档合并成一个文档。我们可以使用 $match、$unwind、$project、$sort、$limit 和 $skip 筛选器来对文档进行筛选、排序和控制结果数量。这些筛选器可以让我们更加灵活地管理数据,满足我们的业务需求。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6489732148841e98947bc398