【问题标题】:Mongo "Error in $cursor stage..." in aggregate pipeline聚合管道中的 Mongo“$cursor 阶段中的错误...”
【发布时间】:2020-10-16 11:16:30
【问题描述】:

我有收藏订单

{_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_idrecommendedProducts.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 以及 thisthat 的帖子,但我仍然无法理清应该如何正确编写聚合管道。到目前为止,我有以下内容

db.orders.aggregate([
 {
    $lookup: {
        "from": "recommendedProducts",
        "as": "recommendations",
        "let": {
            "id": "$user_id"
        },
        "pipeline": [{
                "$match": {
                    "$expr": {
                        "$eq": ["$userId", "$$id"]
                    }
                }
            },
            {
                "$sort": {
                    "Date": -1
                }
            },
            {
                "$limit": 1
            }
        ]
    }
}
])

应该可以正常工作但没有成功。 我需要在这里保留的是推荐产品集合中的最后一个文档,并且只有一个文档来自那里,这就是为什么我也使用排序和限制但我得到错误 "$cursor 阶段中的错误 :: 导致: : 操作超出时间限制" 这里的错误在哪里?

【问题讨论】:

    标签: arrays mongodb mongodb-query aggregation-framework lookup


    【解决方案1】:

    当使用letpipeline$lookup 形式时,以及在使用$expr 时,查询规划器目前无法有效地使用索引。

    这意味着对于每个订单,查找阶段正在扫描整个推荐产品集合以查找匹配的文档。

    如果您要使用其他形式的查找,并且在推荐产品集合中的userId 字段上有一个索引,它将能够使用该索引更快地找到匹配的产品,然后您可以使用 unwind 、排序和分组,或者只是减少以获得最新的值。

    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"
                    }
                }
            }
       }
     }}
    ])
    

    【讨论】:

    • 非常感谢!!所以看起来管道确实不适合这种情况。
    • 请问,如何在recommendations.rankedList 中找到product_id 的位置索引?我正在使用indexOfArray,但没有结果
    • $indexOfArray 只进行完全匹配,因此您必须搜索整个对象,完全匹配所有字段名称和值,并且字段顺序相同
    • 这意味着我应该对排名列表使用 unwind 对吗?
    • 如果不能准确匹配文档,那就是下一个选择。
    猜你喜欢
    • 2019-06-03
    • 2021-09-08
    • 2021-07-14
    • 2020-05-29
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 2019-02-03
    • 2019-03-03
    相关资源
    最近更新 更多