3

我收集了以下数据:

{
  "_id" : ObjectId("51f1fcc08188d3117c6da351"),
  "cust_id" : "abc123",
  "ord_date" : ISODate("2012-10-03T18:30:00Z"),
  "status" : "A",
  "price" : 25,
  "items" : [{
      "sku" : "ggg",
      "qty" : 7,
      "price" : 2.5
    }, {
      "sku" : "ppp",
      "qty" : 5,
      "price" : 2.5
    }]
}

我正在使用查询:

cmd { "aggregate" : "orders" , "pipeline" : [ 
    { "$unwind" : "$items"} , 
    { "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}} , 
    { "$group" : { "price" : { "$first" : "$price"} , "items" : { "$push" : { "sku" : "$items.sku"}} , "_id" : { "items" : "$items"}}} , 
    { "$sort" : { "price" : -1}} , 
    { "$project" : { "_id" : 0 , "price" : 1 , "items" : 1}}
]}

无法理解出了什么问题

4

2 回答 2

9

那是因为你在做$match之后$unwind$unwind生成一个items不再是数组的新文档流(请参阅文档)。

它发出每个文档的次数与其中的项目一样多。

如果要选择其中包含所需元素的文档,然后处理其所有文档,则应$match首先调用:

db.orders.aggregate(
  { "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}},
  { "$unwind" : "$items"},
  ...
);

如果要选择要处理的项目,则应$unwind删除$elemMatch

db.orders.aggregate(
  { "$unwind" : "$items"},
  { "$match" : { "items.qty" : { "$in" : [7]}}},
  ...
);

在第一种情况下,您将获得两个文件:

{ 
  "price" : 25,
  "items" : [
    {"sku" : "ppp"}
  ]
},
{
  "price" : 25,
  "items" : [
    {"sku" : "ggg"}
  ]
}

在第二种情况下,你会得到一个:

{
  "price" : 25,
  "items" : [
    {"sku" : "ggg"}
  ]
}

更新。之后$unwind您的文件将如下所示:

{
  "_id" : ObjectId("51f1fcc08188d3117c6da351"),
  "cust_id" : "abc123",
  "ord_date" : ISODate("2012-10-03T18:30:00Z"),
  "status" : "A",
  "price" : 25,
  "items" : {
    "sku" : "ggg",
    "qty" : 7,
    "price" : 2.5
  }
}
于 2013-08-05T07:57:54.153 回答
3

对于少量文档,展开和匹配就可以了。但是大量的文档,最好做 - 匹配($elemMatch),展开,然后再次匹配。

db.orders.aggregate(
  { "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}},
  { "$unwind" : "$items"},
  { "$match" : { "items.qty" : { "$in" : [7]}}}
  ...
  ...
);

第一个匹配项将仅过滤符合数量标准的文档。在选定的文档中,第二个匹配将删除与数量标准不匹配的子文档。

于 2015-03-02T06:06:28.700 回答