我有订单
{_id: ObjectId("5e32d0fadf54cb3d81293fb3"),
user_id:'test_user',
product_id:'product_2_id'
created_at:'2020-02-25T07:04:05.439+00:00'
}
我需要加入 recommendedProducts 集合,该集合具有 orders.user_id 作为公用密钥,而 recommendedProducts.userId 类似于< / p>
{_id: ObjectId("5e3ac145df54cbeca6230924"),
userId:'test_user'
rankedList:[
0:{Name:'Product_4',id:'product_4_id'},
1:{Name:'Product_1',id:'product_1_id'},
2:{Name:'Product_2',id:'product_2_id'}],
Date:'2020-02-25T06:03:55.439+00:00'
}
{_id: ObjectId("5e388da4df54cb8efb47e61b"),
userId:'test_user'
rankedList:[
0:{Name:'Product_5',id:'product_5_id'},
1:{Name:'Product_6',id:'product_6_id'},
2:{Name:'Product_3',id:'product_3_id'}],
Date:'2020-02-25T05:03:55.439+00:00'
}
我已经阅读了this以及this和that的帖子,但是我仍然无法弄清应该如何正确编写聚合管道。到目前为止,我有以下内容
db.orders.aggregate([
{
$lookup: {
"from": "recommendedProducts",
"as": "recommendations",
"let": {
"id": "$user_id"
},
"pipeline": [{
"$match": {
"$expr": {
"$eq": ["$userId", "$$id"]
}
}
},
{
"$sort": {
"Date": -1
}
},
{
"$limit": 1
}
]
}
}
])
应该可以正常运行,但不会成功。 我需要在这里保留的是collectionProductsProducts集合中的最后一个文档,并且那里只有一个文档,这就是为什么我也使用sort和limit,但是却收到错误“ $ cursor stage错误::的原因: :操作超出了时间限制” 错误在哪里?
答案 0 :(得分:3)
在使用$lookup
和let
形式的pipeline
时,以及在使用$expr
时,查询计划器当前都无法有效地使用索引
这意味着对于每个订单,查找阶段都在扫描整个RecommendationProducts集合以查找匹配的文档。
如果您要使用其他形式的查找,并且在RecommendationProducts集合中的userId
字段上具有索引,则可以使用该索引更快地找到匹配的产品,然后可以使用展开,排序和分组,或者只是减少以获取最新值。
db.orders.aggregate([
{
$lookup: {
"from": "recommendedProducts",
"as": "recommendations",
"localField": "user_id",
"foreignField": "userId"
},
{$addFields: {
recommendations:{
$reduce: {
input: "$recommendations",
initialValue: {$arrayElemAt:["$recommendations",0]},
in: {
$cond: {
if: {$gt:["$$this.Date","$$value.Date"]},
then: "$$this",
else: "$$value"
}
}
}
}
}}
])