考虑这些文件:
{
"Field1":"Test_1",
"Speaker":1,
"Listener":2,
"ListenTime": ISODate("2016-10-15T14:17:49.336Z")
},
{
"Field1":"Test_2",
"Speaker":1,
"Listener":2,
"ListenTime": ISODate("2016-10-13T14:17:49.336Z")
},
{
"Field1":"Test_3",
"Speaker":1,
"Listener":3,
"ListenTime": ISODate("2016-10-10T14:10:49.336Z")
}
我要做的是在MongoDB(3.2)中使用单个查询仅提取由Speaker和Listener对它们进行分组的文档,仅使用最旧的ListenTime文档。
所以,在这种情况下,结果将是:
{
"Field1":"Test_1",
"Speaker":1,
"Listener":2,
"ListenTime": ISODate("2016-10-15T14:17:49.336Z")
},
{
"Field1":"Test_3",
"Speaker":1,
"Listener":3,
"ListenTime": ISODate("2016-10-10T14:10:49.336Z")
}
单个查询是否可以做到这一点?
答案 0 :(得分:1)
聚合框架可用于实现此目的。在第一阶段,使用$group
按Speaker和Listener对文档进行分组。在此阶段,使用$push
运算符将组中的所有文档添加到列表中,并使用$max
运算符计算最近的ListenTime。按照此$redact
阶段,使用列表中最近的ListenTime保留文档。然后,使用$unwind
阶段将列表展平为文档。然后,使用最终的$project
阶段来获取所需的字段。
聚合查询将如下所示。
db.sampleCollection.aggregate([
{
"$group":{
"_id":{"Speaker":"$Speaker", "Listener":"$Listener"},
ListenTime : {"$max":"$ListenTime"},
"docs":{"$push":"$$ROOT"}
}
},
{
$redact:{
$cond:[{$eq:["$ListenTime","$$ROOT.ListenTime"]},"$$DESCEND","$$PRUNE"]
}
},
{
"$project":{
"ListenTime":1,
"Field1":"$docs.0.Field1",
"Speaker":"$docs.0.Speaker",
"Listener":"$docs.0.Listener"
}
}
])
示例输出:
{
"ListenTime" : ISODate("2016-10-10T14:10:49.336Z"),
"Field1" : "Test_3",
"Speaker" : 1,
"Listener" : 3
}
{
"ListenTime" : ISODate("2016-10-15T14:17:49.336Z"),
"Field1" : "Test_1",
"Speaker" : 1,
"Listener" : 2
}
答案 1 :(得分:1)
运行以下聚合管道以获得所需的结果:
db.collection.aggregate([
{ "$sort": { "ListenTime": -1 } },
{
"$group": {
"_id": {
"Speaker": "$Speaker",
"Listener": "$Listener"
},
"Field1" : { "$first": "$Field1" },
"ListenTime" : { "$first": "$ListenTime" }
}
},
{
"$project": {
"Field1": 1,
"Speaker": "$_id.Speaker",
"Listener": "$_id.Listener",
"ListenTime": 1,
"_id": 0
}
}
])
示例输出
/* 1 */
{
"Field1" : "Test_3",
"ListenTime" : ISODate("2016-10-10T14:10:49.336Z"),
"Speaker" : 1,
"Listener" : 3
}
/* 2 */
{
"Field1" : "Test_1",
"ListenTime" : ISODate("2016-10-15T14:17:49.336Z"),
"Speaker" : 1,
"Listener" : 2
}