在我的Meteor应用程序中,我有一组文档,其中包含一系列子文档,如下所示:
/* 1 */
{
"_id" : "5xF9iDTj3reLDKNHh",
"name" : "Lorem ipsum",
"revisions" : [
{
"number" : 0,
"comment" : "Dolor sit amet",
"created" : ISODate("2016-02-11T01:22:45.588Z")
}
],
"number" : 1
}
/* 2 */
{
"_id" : "qTF8kEphNoB3eTNRA",
"name" : "Consecitur quinam",
"revisions" : [
{
"comment" : "Hoste ad poderiquem",
"number" : 1,
"created" : ISODate("2016-02-11T23:25:46.033Z")
},
{
"number" : 0,
"comment" : "Fagor questibilus",
"created" : ISODate("2016-02-11T01:22:45.588Z")
}
],
"number" : 2
}
我想要做的是查询此集合,并按created
数组的revisions
字段中的最大日期对结果集进行排序。我还没有能够完成的事情。我有一些限制:
revisions.created
排序不会削减它,因为从集合中使用的日期取决于排序方向。无论排序顺序如何,我都必须在集合中使用最大日期。revisions
数组将被预先排序。$project
。答案 0 :(得分:3)
你在这里要问的基本问题归结为这样一个事实,即所讨论的数据在一个"数组内,因此MongoDB对如何处理这些数据做了一些基本的假设
如果您按照"降序排序"进行排序,那么MongoDB将完全按照您的要求进行排序,并按照"最大的"数组中指定字段的值:
.sort({ "revisions.created": -1 ))
但是,如果你改为排序"升序"当然,顺序是正确的,最小的"价值被考虑。
.sort({ "revisions.created": 1 })
所以这样做的唯一方法就是计算出数组中数据的最大日期,然后对结果进行排序。这基本上意味着应用.aggregate()
,这对于meteor来说是一个服务器端操作,不幸的是这样:
Collection.aggregate([
{ "$unwind": "$revisions" },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"revisions": { "$push": "$revisions" },
"number": { "$first": "$number" }
"maxDate": { "$max": "$revisions.created" }
}},
{ "$sort": { "maxDate": 1 }
])
或者至多使用MongoDB 3.2,其中$max
可以直接应用于数组表达式:
Collection.aggregate([
{ "$project": {
"name": 1,
"revisions": 1,
"number": 1,
"maxDate": {
"$max": {
"$map": {
"input": "$revisions",
"as": "el",
"in": "$$el.created"
}
}
}
}},
{ "$sort": { "maxDate": 1 } }
])
但实际上两者都不是那么好,即使MongoDB 3.2方法的开销低于以前版本的开销,但由于需要,它仍然没有达到性能方面的好传递数据并计算出值以进行排序。
因此,对于最佳表现,"始终"保留您需要的数据"外部"数组。为此,有$max
"update"运算符,它只会替换文档中的值"如果"提供的值大于"大于"已有的现有价值。即:
Collection.update(
{ "_id": "qTF8kEphNoB3eTNRA" },
{
"$push": {
"revisions": { "created": new Date("2016-02-01") }
},
"$max": { "maxDate": new Date("2016-02-01") }
}
)
这意味着您想要的价值将始终是"已存在于具有预期值的文档中,因此现在只需对该字段进行排序即可:
.sort({ "maxDate": 1 })
因此,对于我的钱,我会使用任何.aggregate()
语句中的任何一个来查看现有数据,并使用这些结果更新每个文档以包含" maxDate"领域。然后更改阵列数据的所有添加和修订的编码,以便在每次更改时应用$max
"update"。
如果你经常使用它,那么拥有一个坚实的领域而不是计算总是更有意义。维护很简单。
在任何情况下,考虑上面应用的例子日期,即"小于"其他最大日期将以各种形式返回给我:
{
"_id" : "5xF9iDTj3reLDKNHh",
"name" : "Lorem ipsum",
"revisions" : [
{
"number" : 0,
"comment" : "Dolor sit amet",
"created" : ISODate("2016-02-11T01:22:45.588Z")
}
],
"number" : 1,
"maxDate" : ISODate("2016-02-11T01:22:45.588Z")
}
{
"_id" : "qTF8kEphNoB3eTNRA",
"name" : "Consecitur quinam",
"revisions" : [
{
"comment" : "Hoste ad poderiquem",
"number" : 1,
"created" : ISODate("2016-02-11T23:25:46.033Z")
},
{
"number" : 0,
"comment" : "Fagor questibilus",
"created" : ISODate("2016-02-11T01:22:45.588Z")
},
{
"created" : ISODate("2016-02-01T00:00:00Z")
}
],
"number" : 2,
"maxDate" : ISODate("2016-02-11T23:25:46.033Z")
}
正确地将第一个文档放在排序顺序的顶部并考虑到" maxDate"。