如何仅从组中查询具有最新时间戳的文档?
Posted
技术标签:
【中文标题】如何仅从组中查询具有最新时间戳的文档?【英文标题】:How to query only documents with the latest timestamp from a group? 【发布时间】:2014-03-08 07:36:26 【问题描述】:在我查询的 MongoDB 集合中,每个文档代表特定时间的一个项目。更新文档时,会创建一个具有相同项目 ID 和新时间戳的新文档。所有项目都有唯一的项目 ID。
为了说明,考虑这个例子。我们从一个项目的一个修订开始:
_id: x,
itemId: 123,
createdOn: ISODate("2013-01-30T11:16:20.102Z"),
field1: "foo",
field2: "bar
更新后,我们有两个版本的项目,具有相同的 itemId 和不同的时间戳。
[
_id: x,
itemId: 123,
createdOn: ISODate("2013-01-30T11:16:20.102Z"),
field1: "foo",
field2: "bar"
,
_id: y,
itemId: 123,
createdOn: ISODate("2014-02-09T14:26:20.102Z"),
field1: "baz",
field2: "fiz"
]
如何找到在其最新修订版中满足特定查询的所有项目?
我目前(错误)的做法是先找到匹配的文档,然后按时间戳排序,按itemId分组,然后从组中的第一个文档返回值:
ItemModel.aggregate( $match: field1: "foo" ).sort(createdOn: -1).group(
_id: '$itemId', // grouping key
createdOn: $first: '$createdOn',
field1: $first: '$field1',
field2: $first: '$field2'
).exec(...);
这是错误的,因为它匹配项目的旧版本。只有项目的最新版本应该匹配。在上面的示例中,此方法返回项目“123”,而正确的结果是一个空结果集。
【问题讨论】:
【参考方案1】:当您可以在聚合管道中做所有事情时,您在这里混合了几种方法。否则,只需按正确的顺序执行步骤即可:
db.collection.aggregate([
$sort: createdOn: -1 ,
$group: _id: "$itemId",
createdOn: $first: "$createdOn",
field1: $first: "$field1" ,
field2: $first: "$field2"
,
$match: field1: "foo"
])
所以首先对最新的文档进行排序。对itemId
进行分组($first 将保持顺序),然后在必要时使用 $match 进行过滤。但您的分组文档将是最新的。
【讨论】:
谢谢,我还没有意识到聚合管道有多灵活。我最终在开始和结束时都有一个匹配步骤,因为这通过减少通过管道的文档数量来提高性能。【参考方案2】:可以考虑更改文档的架构以更好地适应您的查询,并减少聚合开销。您可以将修订子文档推送到数组中并在父文档中维护最新修订,而不是为每个修订创建一个新文档;例如:
_id: x,
itemId: 123,
createdOn: ISODate("2014-02-09T14:26:20.102Z"),
field1: "baz",
field2: "fiz,
revisions: [
createdOn: ISODate("2013-01-30T11:16:20.102Z"), field1: "foo", field2: "bar",
createdOn: ISODate("2014-02-09T14:26:20.102Z"), field1: "baz", field2: "fiz"
]
请记住,MongoDB 强制执行 16MB 的文档大小限制;这应该足以满足大多数用例。这将使您的查询非常简单:db.collection.find(field1: "foo")
只是另一种方法......
【讨论】:
谢谢!这是一个好主意,因为当前模式在计算查询时也很麻烦。我必须运行整个聚合管道才能获得正确的项目数。以上是关于如何仅从组中查询具有最新时间戳的文档?的主要内容,如果未能解决你的问题,请参考以下文章