Mongo "Error in $cursor stage..." 在聚合管道中
Mongo "Error in $cursor stage..." in aggregate pipeline
我有collection订单
{_id: ObjectId("5e32d0fadf54cb3d81293fb3"),
user_id:'test_user',
product_id:'product_2_id'
created_at:'2020-02-25T07:04:05.439+00:00'
}
我需要加入 collection recommendedProducts 并把 orders.user_id 作为通用键recommendedProducts.userId 看起来像
{_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 and also and 篇文章,但我仍然无法理清应该如何正确编写聚合管道。到目前为止,我有以下
db.orders.aggregate([
{
$lookup: {
"from": "recommendedProducts",
"as": "recommendations",
"let": {
"id": "$user_id"
},
"pipeline": [{
"$match": {
"$expr": {
"$eq": ["$userId", "$$id"]
}
}
},
{
"$sort": {
"Date": -1
}
},
{
"$limit": 1
}
]
}
}
])
这应该可以正常工作但没有成功。
我需要保留在这里的是来自 collection 推荐产品的最后一个文档,并且只有一个文档来自那里,这就是为什么我也使用排序和限制但我得到错误 "$cursor 中的错误stage :: :: operation exceeded time limit
这里哪里出错了?
当使用采用 let
和 pipeline
的 $lookup
形式时,以及当使用 $expr
时,查询规划器目前无法有效地使用一个索引。
这意味着对于每个订单,查找阶段正在扫描整个 recommendedProducts 集合以查找匹配的文档。
如果您要使用其他形式的查找,并且在 recommendedProducts 集合中的 userId
字段上有一个索引,则可以使用该索引更快地找到匹配的产品,并且您然后可以使用 unwind、sort 和 group,或者只是 reduce 来获取最新的值。
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"
}
}
}
}
}}
])
我有collection订单
{_id: ObjectId("5e32d0fadf54cb3d81293fb3"),
user_id:'test_user',
product_id:'product_2_id'
created_at:'2020-02-25T07:04:05.439+00:00'
}
我需要加入 collection recommendedProducts 并把 orders.user_id 作为通用键recommendedProducts.userId 看起来像
{_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 and also
db.orders.aggregate([
{
$lookup: {
"from": "recommendedProducts",
"as": "recommendations",
"let": {
"id": "$user_id"
},
"pipeline": [{
"$match": {
"$expr": {
"$eq": ["$userId", "$$id"]
}
}
},
{
"$sort": {
"Date": -1
}
},
{
"$limit": 1
}
]
}
}
])
这应该可以正常工作但没有成功。 我需要保留在这里的是来自 collection 推荐产品的最后一个文档,并且只有一个文档来自那里,这就是为什么我也使用排序和限制但我得到错误 "$cursor 中的错误stage :: :: operation exceeded time limit 这里哪里出错了?
当使用采用 let
和 pipeline
的 $lookup
形式时,以及当使用 $expr
时,查询规划器目前无法有效地使用一个索引。
这意味着对于每个订单,查找阶段正在扫描整个 recommendedProducts 集合以查找匹配的文档。
如果您要使用其他形式的查找,并且在 recommendedProducts 集合中的 userId
字段上有一个索引,则可以使用该索引更快地找到匹配的产品,并且您然后可以使用 unwind、sort 和 group,或者只是 reduce 来获取最新的值。
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"
}
}
}
}
}}
])