我想推送一个对象来指定字段名而不是数组。我尝试了$ push但是我丢失了有关字段插入数组的名称的信息。 我的收藏是:
/* 1 */
{
"_id" : ObjectId("57614a7bd75df17df3013903"),
"O":"aa",
"D":"bb",
"month":1,
"year":2015,
"freq":5
}
/* 2 */
{
"_id" : ObjectId("57614a7bd75df17df3013904"),
"O":"aa",
"D":"bb",
"month":2,
"year":2015,
"freq":5
}
/* 3 */
{
"_id" : ObjectId("57614a7bd75df17df3013905"),
"O":"aa",
"D":"bb",
"month":1,
"year":2016,
"freq":5
}
我想存储对应于字段的所有freq:O和D. 这是我的预期输出:
"_id" : ...,
"O" : "aa",
"D" : "bb",
"freq" : {
"2015" : {
"1" : 5,
"2":5
},
"2016" : {
"1" : 5
}
}
}
我试过了:
db.collection.aggregate([
{
'$group':
{
_id:{"O":"$O","D":"$D","Y":"$year"},
"freq" :{$push: "$freq"}
}
},
{
'$group':
{
_id:{"O":"$O","D":"$D"},
"freq" :{$push: "$freq"}
}
})]
但我得到的数组没有年或月的信息。
谢谢
答案 0 :(得分:1)
您在查询中使用了两个$ group
您的第一个群组查询足以构建您期望的数据。
如果我们正在执行第一个查询
db.stackoverflow.aggregate([
{
'$group':
{
_id:{"O":"$O","D":"$D","Y":"$year"},
"freq" :{$push: "$freq"}
}
}]);
然后结果是
{ "_id" : { "O" : "aa", "D" : "bb", "Y" : 2016 }, "freq" : [ 5 ] }
{ "_id" : { "O" : "aa", "D" : "bb", "Y" : 2015 }, "freq" : [ 5, 5 ] }
现在,如果您执行第二个$ group查询
db.stackoverflow.aggregate([
{
'$group':
{
_id:{"O":"$O","D":"$D"},
"freq" :{$push: "$freq"}
}
}])
然后结果是
{ "_id" : { "O" : "aa", "D" : "bb" }, "freq" : [ 5, 5, 5 ] }
<强>原因:强>
第一个$ group查询中获取的值未传递给第二个$ group查询。
<强>解决方案:强>
使用聚合管道中提供的 $ project ,该管道将仅包含指定字段的文档传递到聚合管道中的下一个阶段。指定的字段可以是输入文档或新计算字段中的现有字段。
https://docs.mongodb.com/manual/reference/operator/aggregation/project/
以下是获得预期结果的查询
db.collection.aggregate([
{
'$group': {
_id: {
"o": "$o",
"d": "$d",
"year": "$year"
},
myArr: {
$push: {
year: "$year",
month: "$month",
freq: "$freq"
}
}
}
},
{
'$group': {
_id: {
"o": "$o",
"d": "$d"
},
myArr1: {
$push: {
year: "$year",
freq: "$myArr"
}
}
}
},
],
{
allowDiskUse: true
})