3

我对 Mongo 很陌生,我很难弄清楚如何编写这个查询。我有一个看起来像这样的订单集合。

{
"_id" : ObjectId("51fade5b8c825bb19d9ef228"),
"o_id" : 1,
...
"order_line" : [
    {
            "ol_id" : 1,
            "ol_o_id" : 1,
            "ol_i_id" : 531,
            "ol_qty" : 280
    },
    {
            "ol_id" : 2,
            "ol_o_id" : 1,
            "ol_i_id" : 90,
            "ol_qty" : 295
    },
    {
            "ol_id" : 3,
            "ol_o_id" : 1,
            "ol_i_id" : 963,
            "ol_qty" : 184
    }
]}

我需要为每件商品找到最畅销的相关商品。

查询需要找到与当前正在查询的 ol_i_id 一起销售的前 5 个项目/ol_i_id。为了做到这一点,查询需要找到所有带有“ol_i_id”的订单,比如“ol_i_id”:531,然后在整个集合中将每个以“ol_i_id”出售的商品的“ol_qty”相加:531。然后用“ol_i_id”出售的前 5 个“ol_i_id”报告:531。

我试图让它尽可能容易理解。

/edit 到目前为止,我有这个。

 db.orders.aggregate( { $match : { order_line: { $elemMatch : { ol_i_id : 531 } } } },
   { $project : { o_id : 1, order_line : 1} },
   { $unwind: "$order_line"},
   { $limit : 5 } )

这使 order_line 看起来像这样。

   "result" : [
           {
                   "_id" : ObjectId("51fade5b8c825bb19d9ef389
                   "o_id" : 354,
                   "order_line" : {
                           "ol_id" : 1,
                           "ol_o_id" : 354,
                           "ol_i_id" : 2,
                           "ol_qty" : 271
                   }
           },
           {
                   "_id" : ObjectId("51fade5b8c825bb19d9ef389
                   "o_id" : 354,
                   "order_line" : {
                           "ol_id" : 2,
                           "ol_o_id" : 354,
                           "ol_i_id" : 707,
                           "ol_qty" : 138
                   }
           }...

该查询只给了我所有使用相关 ol_i_id 购买的 order_lines,531。现在我需要对每个唯一 ol_i_id 的 ol_qty 字段求和,然后返回前 5 个。这类似于您在亚马逊上看到的内容上面写着“买了这个的人也买了这个其他的东西”希望这更有意义。很抱歉在这方面过于冗长。

理想情况下,我希望它以这样的套装回来

 {
    "result" : [
            {
                    "ol_i_id" : 46,
                    "totalSoldWithItem531" : 20012
            },
            {
                    "ol_i_id" : 669,
                    "totalSoldWithItem531" : 19000
            },
            {
                    "ol_i_id" : 5,
                    "totalSoldWithItem531" : 18291
            },
            {
                    "ol_i_id" : 881,
                    "totalSoldWithItem531" : 18101
            },
            {
                    "ol_i_id" : 538,
                    "totalSoldWithItem531" : 17001
            }
    ],
    "ok" : 1
}

/edit 我现在想出了这个,这几乎是我所需要的。

 db.orders.aggregate( { $match : { order_line: { $elemMatch : { ol_i_id : 531 } } } },
    { $project : { o_id : 1, order_line : 1} },
    { $unwind: "$order_line"},
    { $group : { _id : "$order_line.ol_i_id", 
     totalSales : { $sum : "$order_line.ol_qty" } } },
    { $sort : { totalSales : -1 } },
    { $limit : 5 } )

结果看起来像这样。

 {
    "result" : [
            {
                    "_id" : 531,
                    "totalSales" : 10639
            },
            {
                    "_id" : 655,
                    "totalSales" : 520
            },
            {
                    "_id" : 2,
                    "totalSales" : 500
            },
             ....

我的最后一个问题是我如何排除从结果集中查询的项目,因为我对该数字不感兴趣?在这种情况下,我需要从结果中排除 _id : 531 ,因为那是被查询的 id。

4

1 回答 1

4

您自己得到了大部分答案,基本上有两种方法可以排除您查询所依据的原始项目。一种是简单地添加{$match:{_id:{$ne:origID}}}到管道的末端。不过不要忘记更改$limit:5$limit:6,因为您希望在排除项目本身后留下五个项目。

{$match}一种更简单的方法是在管道中更早地添加相同的内容 - 特别是在$unwind. 整个管道(经过一些简化)应如下所示:

db.orders.aggregate( 
    { $match   : { "order_line.ol_i_id" : 531 } } } },
    { $project : { "order_line" : 1, _id:0 } },
    { $unwind  : "$order_line"},
    { $match   : { "order_line.ol_i_id":{"$ne": 531 } } },
    { $group   : { _id : "$order_line.ol_i_id", 
                   totalSales : { $sum : "$order_line.ol_qty" } } },
    { $sort    : { totalSales : -1 } },
    { $limit   : 5 } 
);
于 2013-09-01T21:24:58.580 回答