当前位置: 首页 > 知识库问答 >
问题:

使用聚合[重复]在mongoDB中限制和排序每个分组

奚飞星
2023-03-14

我如何在mongoDB中按对每个组进行排序和限制。

考虑以下数据:

Country:USA,name:xyz,rating:10,id:x
Country:USA,name:xyz,rating:10,id:y
Country:USA,name:xyz,rating:10,id:z
Country:USA,name:abc,rating:5,id:x
Country:India,name:xyz,rating:5,id:x
Country:India,name:xyz,rating:5,id:y
Country:India,name:abc,rating:10,id:z
Country:India,name:abc,rating:10,id:x

现在,我将按国家分组,按评级排序,并将每组的数据限制为2。

所以答案是:

Country:USA
name:xyz,rating:10,id:x
name:xyz,rating:10,id:y
Country:India
name:abc,rating:10,id:x
name:abc,rating:10,id:z

我想只使用聚合框架来实现这一点。

我试图包括排序的评级,但简单的查询后处理没有结果。

共有1个答案

周飞语
2023-03-14

您最好的选择是为每个“国家”运行单独的查询(理想情况下是并行)并返回组合结果。查询非常简单,只需在对评级值应用排序后返回前2个值,即使您需要执行多个查询以获得完整的结果,也会执行得非常快。

聚合框架现在甚至在不久的将来都不适合这种情况。问题是没有这样的操作符以任何方式“限制”任何分组的结果。因此,要做到这一点,您基本上需要将所有内容推送到一个数组中,并从中提取“前n个”值。

当前需要执行的操作非常可怕,核心问题是,在大多数真实数据源上,结果可能会超过BSON对每个文档16MB的限制。

此外,由于您现在必须执行的操作方式,此操作也很复杂。但仅用两个项目进行演示:

db.collection.aggregate([
    // Sort content by country and rating
    { "$sort": { "Country": 1, "rating": -1 } },

    // Group by country and push all items, keeping first result
    { "$group": {
        "_id": "$Country",
        "results": {
            "$push": {
                "name": "$name", 
                "rating": "$rating",
                "id": "$id"
            }
        },
        "first": { 
            "$first": {
                "name": "$name", 
                "rating": "$rating",
                "id": "$id"
            }
        }
    }},

    // Unwind the array
    { "$unwind": "results" },

    // Remove the seen result from the array
    { "$redact": {
        "$cond": {
            "if": { "$eq": [ "$results.id", "$first.id" ] },
            "then": "$$PRUNE",
            "else": "$$KEEP"
        }
    }},

    // Group to return the second result which is now first on stack
    { "$group": {
        "_id": "$_id",
        "first": { "$first": "$first" },
        "second": { 
            "$first": {
                "name": "$results.name", 
                "rating": "$results.rating",
                "id": "$results.id"
            }
        }
    }},

    // Optionally put these in an array format
    { "$project": {
        "results": { 
            "$map": {
                "input": ["A","B"],
                "as": "el",
                "in": {
                    "$cond": {
                        "if": { "$eq": [ "$$el", "A" ] },
                        "then": "$first",
                        "else": "$second"
                    }
                }
            }
        }
    }}
])

这会得到结果,但这不是一个很好的方法,而且随着迭代次数的增加,会变得更加复杂,以获得更高的限制,甚至在某些情况下分组返回的结果可能少于n。

截至编写时,当前的开发系列(3.1. x)有一个$切片运算符,它使这变得更简单,但仍然具有相同的“大小”陷阱:

db.collection.aggregate([
    // Sort content by country and rating
    { "$sort": { "Country": 1, "rating": -1 } },

    // Group by country and push all items, keeping first result
    { "$group": {
        "_id": "$Country",
        "results": {
            "$push": {
                "name": "$name", 
                "rating": "$rating",
                "id": "$id"
            }
        }
    }},
    { "$project": {
        "results": { "$slice": [ "$results", 2 ] }
    }}
])

但基本上,直到聚合框架有某种方法“限制”$ush或类似的分组“限制”运算符产生的项目数量,那么聚合框架并不是这种类型的问题的最佳解决方案。

像这样的简单查询:

js prettyprint-override">db.collection.find({ "Country": "USA" }).sort({ "rating": -1 }).limit(1)

为每个不同的国家运行,理想情况下通过线程的事件循环并行处理,并结合结果产生当前最优化的方法。它们只获取所需的内容,这是聚合框架在这种分组中尚无法处理的大问题。

因此,请寻找支持,以最理想的方式为您选择的语言执行此“组合查询结果”,因为这将比将此应用于聚合框架要简单得多,性能也要高得多。

 类似资料:
  • 我有一个具有以下模式的待售项目集合: 我继承了一个聚合查询,它返回匹配类别的项目,按商家分组,组按组中的最大评级排序: 在此之后,代码继续按评级对每组中的项目进行排序,并删除除每组中排名前2位之外的所有项目。 作为聚合函数的一部分,是否可以在组内执行此排序和限制,以便聚合只返回每组中评级最高的两个项目?

  • 例如,我有一个收藏: 如何在MongoDB中进行查询以按分组,然后按排序并以进行。我想得到这样的:

  • 本文向大家介绍在MongoDB中执行聚合排序?,包括了在MongoDB中执行聚合排序?的使用技巧和注意事项,需要的朋友参考一下 您可以将method和$sort()运算符一起使用。为了理解这个概念,让我们用文档创建一个集合。使用文档创建集合的查询如下- 在method的帮助下显示集合中的所有文档。查询如下- 以下是输出- 这是对MongoDB聚合排序的查询。 情况1-每当您希望结果按降序排列时。查

  • 在MongoDB聚合管道中,从一个阶段到另一个阶段的记录流一次发生一个/批(或者)将等待当前阶段完成整个收集,然后再将其传递到下一个阶段? 例如,我有一个包含以下示例记录的集合类测试 我总共有大约100名学生的1000条记录,我有以下汇总查询 我有以下问题。 排序顺序在最终结果中丢失。如果我在$group之后放置另一个排序,则结果会正确排序。这是否意味着$group不维护之前的排序顺序? 我想将结

  • 给java类一些东西 我有一张物品清单 我希望能够对它们进行排序,这样它们就可以按照每个父对象的虚数的累积和排序,然后再按照虚数排序。 所以我最终 我知道用parentKey和sum of noThings映射它是 我想,也许包装我的Something类并获得每个父项的总密钥可能会在某种程度上起作用。 但看起来工作量很大,不太优雅。 如有任何意见/想法,将不胜感激。

  • 也许有人知道。。我的mongoDB集合中的每个文档如下所示: 如何找到每个组中强度. a和强度. b之和最大的前10个文档? 示例:我有这样的文件: 我想得到结果: 总之,在本例中,我希望得到按“group”字段分组的结果,并仅从每组中选择前两个字段总数最大的“a”和“b”文档。这是否可行? 到目前为止,我做到了: 但如何排序和限制每个组的数组“用户”中的元素数?