我对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_qty”与“ol_i_id”:531相加在整个集合中。然后报告与“ol_i_id”出售的前5名“ol_i_id”:531。
我试图尽可能地理解这一点。
/编辑 到目前为止,我有这个。
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
}
/编辑我现在想出了这个,这几乎就是我所需要的。
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。
答案 0 :(得分:2)
您自己获得了大部分答案,基本上有两种方法可以排除您基于查询的原始项目。一种是简单地将{$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 }
);