$ elemMatch在MongoDB Aggregation Framework中的$ unwind之后不起作用

Pha*_*jee 3 mongodb aggregation-framework mongo-java

我收集了以下数据:

{
  "_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
    }]
}
Run Code Online (Sandbox Code Playgroud)

我正在使用查询:

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}}
]}
Run Code Online (Sandbox Code Playgroud)

无法理解出了什么问题

Leo*_*tny 8

这是因为你在$match追求$unwind.$unwind生成一个新的文档流,items不再是一个数组(参见文档).

它会发送每个文档的次数与其中的项目一样多.

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

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

如果你想选择之后要处理的项目$unwind,你应该删除$elemMatch:

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

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

{ 
  "price" : 25,
  "items" : [
    {"sku" : "ppp"}
  ]
},
{
  "price" : 25,
  "items" : [
    {"sku" : "ggg"}
  ]
}
Run Code Online (Sandbox Code Playgroud)

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

{
  "price" : 25,
  "items" : [
    {"sku" : "ggg"}
  ]
}
Run Code Online (Sandbox Code Playgroud)

更新.在$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
  }
}
Run Code Online (Sandbox Code Playgroud)