我收集了以下数据:
{
"_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}}
]}
无法理解出现了什么问题
答案 0 :(得分:7)
这是因为你在$match
之后正在$unwind
。 $unwind
生成新的文档流,其中items
不再是数组(see docs)。
它会向每个文档发出与其中的项目一样多的次数。
如果要选择包含所需元素的文档,然后处理其所有文档,则应首先调用$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
}
}
答案 1 :(得分:2)
对于少量文件,放松和匹配很好。但是大量的文件,最好做 - 匹配($ elemMatch),放松,再次匹配。
db.orders.aggregate(
{ "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}},
{ "$unwind" : "$items"},
{ "$match" : { "items.qty" : { "$in" : [7]}}}
...
...
);
第一场比赛将仅过滤与qty标准匹配的文档。在所选文档中,第二个匹配将删除与qty标准不匹配的子文档。