gpt4 book ai didi

mongodb - 按最大数组字段排序,升序或降序

转载 作者:可可西里 更新时间:2023-11-01 09:35:25 24 4
gpt4 key购买 nike

在我的 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
}

我想做的是查询这个集合,并根据 revisions 数组的 created 字段中的 ma​​ximum 对结果集进行排序.我还没有能够完成的事情。我的一些限制是:

  • 仅按 revisions.created 排序并不能解决问题,因为集合中使用的日期取决于排序方向。无论排序顺序如何,我都必须使用集合中的最大日期
  • 我不能依赖于未排序的结果集的查询后操作,因此,这必须通过数据库的适当查询或聚合来完成。
  • 不能保证 revisions 数组会被预先排序。
  • 某些文档中可能有额外的字段,这些字段必须一起出现,因此请谨慎使用 $project
  • Meteor 仍在使用 MongoDB 2.6,较新的 API 功能并不好:(

最佳答案

您在这里提出的问题的基本问题归结为以下事实:所讨论的数据位于“数组”中,因此 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”,正确地将第一个文档放在排序顺序的顶部。

关于mongodb - 按最大数组字段排序,升序或降序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35374433/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com