MongoDB - 查询 - 每组顶级文档

时间:2017-07-28 05:21:26

标签: mongodb aggregation-framework

我有以下SQL(mysql)查询,我想将其转换为MongoDB。它基本上是每组中的前1个文档:

SELECT A.* 
FROM ads AS A
INNER JOIN (SELECT id 
            FROM ads
            WHERE userId = 1
            GROUP BY ad_code
            HAVING MAX(ad_timestamp)) AS B ON B.id = A.id

从我到目前为止所读到的,有几种方法可以在MongoDB中聚合数据(MongoDB aggregation comparison: group(), $group and MapReduce更多信息):

  • 组(不适用于分片集合)
  • MapReduce的
  • $组

我试图用MongoDB聚合框架来解决这个问题。到目前为止,我有这个:

db.ads.aggregate([
    { $match: { userId: ObjectId("5976e215769d8a4a4d75c514") } },
    { 
        $group: { 
            _id: "$ad_code", 
            latestTimestamp: { $max: "$ad_timestamp" },
        }
    }
])

但是这不会返回匹配文档的_ids,只返回广告代码和最大时间戳,因此我无法使用这些数据来获取整个文档。

这个问题看起来非常相关,但它似乎没有解决我遇到的同样问题: Query one document per association from MongoDB

由于

编辑重复标记:此问题与其他问题不同,与我链接的问题不同,因为解决方案使用$first操作数查找1匹配,docIds字段以检索未聚合的原始文档。这与其他问题接近解决方案的方式不同,部分原因是随着时间的推移MongoDB的发展。

1 个答案:

答案 0 :(得分:1)

它没有返回_id,因为您没有要求它。 请尝试此查询:

db.ads.aggregate([
    { $match: { userId: ObjectId("5976e215769d8a4a4d75c514") } },
    { $sort: {"ad_timestamp": -1}},
    { $group: { 
        _id: "$ad_code", 
        latestTimestamp: { $first: "$ad_timestamp" },
        docIds: {$first: "$_id"}
       }
    }
])

此处,我们首先按ad_timestamp排序,并使用 $first 获取每个组的第一个,并_id