Mongodb $lookup on ObjectId';在一个数组中
对一个ObjectId数组而不仅仅是单个ObjectId的字段执行$lookup的语法是什么 订单文件示例:Mongodb $lookup on ObjectId';在一个数组中,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,对一个ObjectId数组而不仅仅是单个ObjectId的字段执行$lookup的语法是什么 订单文件示例: { _id: ObjectId("..."), products: [ ObjectId("..<Car ObjectId>.."), ObjectId("..<Bike ObjectId>..") ] } 期望结果 { _id: ObjectId("..."), products: [ ObjectId("..<
{
_id: ObjectId("..."),
products: [
ObjectId("..<Car ObjectId>.."),
ObjectId("..<Bike ObjectId>..")
]
}
期望结果
{
_id: ObjectId("..."),
products: [
ObjectId("..<Car ObjectId>.."),
ObjectId("..<Bike ObjectId>..")
],
productObjects: [
{<Car Object>},
{<Bike Object>}
],
}
{
_id:ObjectId(“…”),
产品:[
ObjectId(“…”),
ObjectId(“…”)
],
productObjects:[
{},
{}
],
}
2017年更新
<代码>不再需要$unwind
旧答案
聚合管道阶段不会直接与阵列一起工作。设计的主要目的是对可能的相关数据进行“左连接”,作为“一对多”类型的连接(或者实际上是“查找”)。但该值是单数的,而不是数组
因此,在执行$lookup
操作之前,必须先“解除”内容的正常化,才能使其正常工作。这意味着使用:
db.orders.aggregate([
//展开源文件
{“$unwind”:“$products”},
//进行查找匹配
{“$lookup”:{
“来自”:“产品”,
“localField”:“产品”,
“外域”:“\u id”,
“作为”:“productObjects”
}},
//展开结果数组(可能是一个或无)
{“$unwind”:“$productObjects”},
//分组回阵列
{“$组”:{
“\u id”:“$\u id”,
“产品”:{“$push”:“$products”},
“productObjects”:{“$push”:“$productObjects”}
}}
])
在$lookup
匹配每个数组成员后,结果就是一个数组本身,因此您可以再次$unwind
并使用新数组获得最终结果
请注意,任何未找到的“左连接”匹配项都将为给定产品上的“productObjects”创建一个空数组,从而在调用第二个$unwind
时否定“product”元素的文档
虽然直接应用到数组会很好,但它只是通过将单个值与可能的多个值进行匹配来实现的
由于$lookup
基本上是非常新的,因此它目前的工作方式与那些熟悉那里提供的.populate()
方法的“穷人版”的人所熟悉的一样。不同之处在于,$lookup
提供了“连接”的“服务器端”处理,而不是在客户机上,$lookup
中的一些“成熟度”目前缺乏.populate()
提供的功能(例如直接在数组上插入查找)
这实际上是一个需要改进的问题,所以如果运气好的话,它将在下一个版本或之后不久发布
作为一个设计原则,您当前的结构既不好也不坏,只是在创建任何“连接”时会受到开销的影响。因此,MongoDB在inception中的基本原则是适用的,如果您“可以”在一个集合中“预先加入”数据,那么最好这样做
作为一般原则,$lookup
可以说的另一件事是,此处“连接”的目的是以与此处所示不同的方式工作。因此,与其将其他文档的“相关ID”保存在“父级”文档中,最好的一般原则是“相关文档”包含对“父级”的引用
因此,$lookup
可以说是“最有效”的“关系设计”,与mongoose.populate()
执行客户端连接的方式相反。通过在每个“多”中标识“一”,您只需拉入相关项,而无需先$unwind
数组。2017更新
<代码>不再需要$unwind
旧答案
聚合管道阶段不会直接与阵列一起工作。设计的主要目的是对可能的相关数据进行“左连接”,作为“一对多”类型的连接(或者实际上是“查找”)。但该值是单数的,而不是数组
因此,在执行$lookup
操作之前,必须先“解除”内容的正常化,才能使其正常工作。这意味着使用:
db.orders.aggregate([
//展开源文件
{“$unwind”:“$products”},
//进行查找匹配
{“$lookup”:{
“来自”:“产品”,
“localField”:“产品”,
“外域”:“\u id”,
“作为”:“productObjects”
}},
//展开结果数组(可能是一个或无)
{“$unwind”:“$productObjects”},
//分组回阵列
{“$组”:{
“\u id”:“$\u id”,
“产品”:{“$push”:“$products”},
“productObjects”:{“$push”:“$productObjects”}
}}
])
在$lookup
匹配每个数组成员后,结果就是一个数组本身,因此您可以再次$unwind
并使用新数组获得最终结果
请注意,任何未找到的“左连接”匹配项都将为给定产品上的“productObjects”创建一个空数组,从而在调用第二个$unwind
时否定“product”元素的文档
虽然直接应用到数组会很好,但它只是通过将单个值与可能的多个值进行匹配来实现的
由于$lookup
基本上是非常新的,因此它目前的工作方式与那些熟悉那里提供的.populate()
方法的“穷人版”的人所熟悉的一样。不同之处在于,$lookup
提供了“连接”的“服务器端”处理,而不是在客户机上,$lookup
中的一些“成熟度”目前缺乏.populate()
提供的功能(例如直接在数组上插入查找)
这实际上是一个需要改进的问题,所以如果运气好的话,它将在下一个版本或之后不久发布
作为一个设计原则,您当前的结构既不好也不坏,只是在创建任何“连接”时会受到开销的影响。因此,t
{
_id: ObjectId("..."),
products: [
ObjectId("..<Car ObjectId>.."),
ObjectId("..<Bike ObjectId>..")
],
productObjects: [
{<Car Object>},
{<Bike Object>}
],
}
db.getCollection('vehicles').aggregate([
{
$match: {
status: "AVAILABLE",
vehicleTypeId: {
$in: Array.from(newSet(d.vehicleTypeIds))
}
}
},
{
$lookup: {
from: "servicelocations",
localField: "locationId",
foreignField: "serviceLocationId",
as: "locations"
}
},
{
$unwind: "$locations"
}
]);
{
"_id" : ObjectId("59c3983a647101ec58ddcf90"),
"vehicleId" : "45680",
"regionId" : 1.0,
"vehicleTypeId" : "10TONBOX",
"locationId" : "100",
"description" : "Isuzu/2003-10 Ton/Box",
"deviceId" : "",
"earliestStart" : 36000.0,
"latestArrival" : 54000.0,
"status" : "AVAILABLE",
"accountId" : 1.0,
"locations" : {
"_id" : ObjectId("59c3afeab7799c90ebb3291f"),
"serviceLocationId" : "100",
"regionId" : 1.0,
"zoneId" : "DXBZONE1",
"description" : "Masafi Park Al Quoz",
"locationPriority" : 1.0,
"accountTypeId" : 0.0,
"locationType" : "DEPOT",
"location" : {
"makani" : "",
"lat" : 25.123091,
"lng" : 55.21082
},
"deliveryDays" : "MTWRFSU",
"timeWindow" : {
"timeWindowTypeId" : "1"
},
"address1" : "",
"address2" : "",
"phone" : "",
"city" : "",
"county" : "",
"state" : "",
"country" : "",
"zipcode" : "",
"imageUrl" : "",
"contact" : {
"name" : "",
"email" : ""
},
"status" : "",
"createdBy" : "",
"updatedBy" : "",
"updateDate" : "",
"accountId" : 1.0,
"serviceTimeTypeId" : "1"
}
}
{
"_id" : ObjectId("59c3983a647101ec58ddcf91"),
"vehicleId" : "81765",
"regionId" : 1.0,
"vehicleTypeId" : "10TONBOX",
"locationId" : "100",
"description" : "Hino/2004-10 Ton/Box",
"deviceId" : "",
"earliestStart" : 36000.0,
"latestArrival" : 54000.0,
"status" : "AVAILABLE",
"accountId" : 1.0,
"locations" : {
"_id" : ObjectId("59c3afeab7799c90ebb3291f"),
"serviceLocationId" : "100",
"regionId" : 1.0,
"zoneId" : "DXBZONE1",
"description" : "Masafi Park Al Quoz",
"locationPriority" : 1.0,
"accountTypeId" : 0.0,
"locationType" : "DEPOT",
"location" : {
"makani" : "",
"lat" : 25.123091,
"lng" : 55.21082
},
"deliveryDays" : "MTWRFSU",
"timeWindow" : {
"timeWindowTypeId" : "1"
},
"address1" : "",
"address2" : "",
"phone" : "",
"city" : "",
"county" : "",
"state" : "",
"country" : "",
"zipcode" : "",
"imageUrl" : "",
"contact" : {
"name" : "",
"email" : ""
},
"status" : "",
"createdBy" : "",
"updatedBy" : "",
"updateDate" : "",
"accountId" : 1.0,
"serviceTimeTypeId" : "1"
}
}
db.products.aggregate([
{ '$lookup': {
'from': 'products',
'let': { 'pid': '$products' },
'pipeline': [
{ '$match': { '$expr': { '$in': ['$_id', '$$pid'] } } }
// Add additional stages here
],
'as':'productObjects'
}
])