在我查询的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”,而正确的结果是空结果集。
答案 0 :(得分: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进行过滤。但是您的分组文档将是最新的。
答案 1 :(得分:1)
可以考虑更改文档的架构以更好地适应您的查询,并减少聚合的开销。您可以将修订子文档推送到数组并在父文档中维护最新修订,而不是为每个修订创建新文档;例如:
{
_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”})
只是另一种方法......