对作为 ObjectId 数组而不是单个 ObjectId 的字段执行 $lookup 的语法是什么?
示例订单文件:
{
_id: ObjectId("..."),
products: [
ObjectId("..<Car ObjectId>.."),
ObjectId("..<Bike ObjectId>..")
]
}
不工作的查询:
db.orders.aggregate([
{
$lookup:
{
from: "products",
localField: "products",
foreignField: "_id",
as: "productObjects"
}
}
])
想要的结果
{
_id: ObjectId("..."),
products: [
ObjectId("..<Car ObjectId>.."),
ObjectId("..<Bike ObjectId>..")
],
productObjects: [
{<Car Object>},
{<Bike Object>}
],
}
最佳答案
$lookup can now directly use an array as the local field . $unwind
不再需要。
$lookup
聚合管道阶段不能直接与数组一起使用。设计的主要目的是将“左连接”作为可能相关数据上的“一对多”连接(或实际上是“查找”)。但该值应为单数,而不是数组。
因此,您必须在执行 $lookup
操作之前首先对内容进行“反规范化”才能使其正常工作。这意味着使用 $unwind
:
db.orders.aggregate([
// Unwind the source
{ "$unwind": "$products" },
// Do the lookup matching
{ "$lookup": {
"from": "products",
"localField": "products",
"foreignField": "_id",
"as": "productObjects"
}},
// Unwind the result arrays ( likely one or none )
{ "$unwind": "$productObjects" },
// Group back to arrays
{ "$group": {
"_id": "$_id",
"products": { "$push": "$products" },
"productObjects": { "$push": "$productObjects" }
}}
])
$lookup
匹配每个数组成员后,结果就是一个数组本身,所以你再次$unwind
和$group
至$push
最终结果的新数组。
请注意,任何未找到的“左连接”匹配项将为给定产品上的“productObjects”创建一个空数组,从而在第二个 $unwind
被调用。
虽然直接应用到数组会很好,但目前这就是通过将奇异值与可能的多个匹配来实现的。
由于 $lookup
基本上是非常新的,它目前的工作方式与熟悉 mongoose 的人一样。作为那里提供的 .populate()
方法的“可怜的版本”。区别在于 $lookup
提供“连接”的“服务器端”处理,而不是在客户端上,并且 $lookup
中的一些“成熟度”目前是缺少 .populate()
提供的功能(例如直接在数组上插入查找)。
这实际上是一个指定的改进问题 SERVER-22881 ,所以运气好的话,它会在下一个版本或不久之后发布。
作为设计原则,您当前的结构既不好也不坏,只是在创建任何“连接”时会产生开销。因此,MongoDB 在初始阶段的基本原则适用,如果您“可以”使用“预先加入”的数据在一个集合中,那么最好这样做。
另一件事可以说是 $lookup
作为一般原则,这里“加入”的意图是与这里显示的相反。因此,与其将其他文档的“相关 ID”保留在“父”文档中,最佳的一般原则是“相关文档”包含对“父”的引用。
所以 $lookup
可以说是“工作最好”的“关系设计”,这与 mongoose .populate()
之类的东西如何执行它的客户端相反侧连接。通过在每个“多”中标识“一”,您只需拉入相关项目,而无需先 $unwind
数组。
https://stackoverflow.com/questions/34967482/
相关文章:
mongodb - 无法验证到 mongo, "auth fails"
mongodb - 如何使用 MongoDB 过滤子文档中的数组
java - Spring Data 的 MongoTemplate 和 MongoReposito
javascript - node.js mongodb 通过_id node-mongodb-na
mongodb - 如何将 mongodb 客户端连接到本地 Meteor MongoDB
MongoDB select count(distinct x) on an indexed col