mongodb count 每个字段/键的不同值的数量

Posted

技术标签:

【中文标题】mongodb count 每个字段/键的不同值的数量【英文标题】:mongodb count num of distinct values per field/key 【发布时间】:2013-02-02 04:28:52 【问题描述】:

是否有一个查询来计算一个字段在 DB 中包含多少不同的值。

f.e 我有一个国家/地区字段,有 8 种国家/地区值(西班牙、英国、法国等)

如果有人添加了更多包含新国家/地区的文档,我希望查询返回 9。

还有比分组计数更简单的方法吗?

【问题讨论】:

你看过aggregation框架吗? 或map-reduce? MongoDB select count(distinct x) on an indexed column - count unique results for large data sets 的可能重复项。我在那里发布了我的答案。 【参考方案1】:

MongoDB 有一个distinct command,它返回一个字段的不同值的数组;您可以检查数组的长度以进行计数。

还有一个shell db.collection.distinct() 助手:

> db.countries.distinct('country');
[ "Spain", "England", "France", "Australia" ]

> db.countries.distinct('country').length
4

如 MongoDB 文档中所述:

结果不得大于最大 BSON 大小 (16MB)。如果您的结果超过最大 BSON 大小,请使用聚合管道使用 $group 运算符检索不同的值,如 Retrieve Distinct Values with the Aggregation Pipeline 中所述。

【讨论】:

如果你的不同值的数量太高,这真的不起作用......如果你正在查看世界上不同的人的名字或其他东西。你有一个可以扩展的答案吗? 1+ 表示长度。我正在努力寻找类似的东西。谢谢。 我不知道他们为什么不在那里使用 count() @MarianKlühspies - 因为它只是一个 javascript 数组,它使用 length 属性来计算元素的数量。 @rohitcoder 如果您有数百万或数十亿个文档要迭代不同的值,我建议发布一个新问题,其中包含您的环境和用例的详细信息。我希望您将使用比 2013 年 2 月的讨论更现代的 MongoDB 版本,当时 MongoDB 2.2 是最新的服务器版本并且刚刚引入了聚合框架:)。我编辑了我的答案以包含来自distinct 文档的注释,该文档建议将聚合框架用于更大的结果集,但在现代版本的 MongoDB 中还有其他方法和运算符可用。【参考方案2】:

您可以利用Mongo Shell Extensions。这是一个单独的 .js 导入,您可以将其附加到您的 $HOME/.mongorc.js,或者以编程方式(如果您也在 Node.js/io.js 中进行编码)。

示例

对于每个不同的字段值,统计在文档中出现的次数,可选地通过查询过滤

> db.users.distinctAndCount('name', name: /^a/i)


  "Abagail": 1,
  "Abbey": 3,
  "Abbie": 1,
  ...

字段参数可以是字段数组

> db.users.distinctAndCount(['name','job'], name: /^a/i)


  "Austin,Educator" : 1,
  "Aurelia,Educator" : 1,
  "Augustine,Carpenter" : 1,
  ...

【讨论】:

如何在节点中导入这个? require("./script.js"),我想 对,但我无法获得里面的功能。我该如何使用它们。它们被定义为 db.protoptype.distinctAndCount repo 的自述文件中有一个操作方法部分(RTFM!1!!1!)基本上,将.mongorc.jsfile 放入您的主目录。完成。【参考方案3】:

这里是使用聚合 API 的示例。为了使情况复杂化,我们从文档的数组属性中按不区分大小写的单词进行分组。

db.articles.aggregate([
    
        $match: 
            keywords:  $not: $size: 0 
        
    ,
     $unwind: "$keywords" ,
    
        $group: 
            _id: $toLower: '$keywords',
            count:  $sum: 1 
        
    ,
    
        $match: 
            count:  $gte: 2 
        
    ,
     $sort :  count : -1 ,
     $limit : 100 
]);

给出的结果如

 "_id" : "inflammation", "count" : 765 
 "_id" : "obesity", "count" : 641 
 "_id" : "epidemiology", "count" : 617 
 "_id" : "cancer", "count" : 604 
 "_id" : "breast cancer", "count" : 596 
 "_id" : "apoptosis", "count" : 570 
 "_id" : "children", "count" : 487 
 "_id" : "depression", "count" : 474 
 "_id" : "hiv", "count" : 468 
 "_id" : "prognosis", "count" : 428 

【讨论】:

登录只是为了+这个答案。谢谢!顺便说一句,如果你在一个独特的领域做,只需删除展开线。 @RichieRich, unwind 是必要的,因为代码正在对与 distinct 工作方式匹配的数组字段的各个值进行分组。 @Paul Richie 所说的是,如果分组只是“常规”字段(字符串、整数等)完成,那么您不需要展开步骤。对不对? @guyarad unwind 在处理数组时是必需的。 +1 的答案,正是我正在做的事情,但不同有其自身的魅力,但这只是黄金:) - 无论如何,我必须阅读更多关于聚合以实现所需的集合过滤数据的结果【参考方案4】:

在 MongoDb 3.4.4 和更高版本中,您可以利用 $arrayToObject 运算符和 $replaceRoot 管道来获取计数。

例如,假设您有一组具有不同角色的用户,并且您想要计算角色的不同计数。您需要运行以下聚合管道:

db.users.aggregate([
     "$group": 
        "_id":  "$toLower": "$role" ,
        "count":  "$sum": 1 
     ,
     "$group": 
        "_id": null,
        "counts": 
            "$push":  "k": "$_id", "v": "$count" 
        
     ,
     "$replaceRoot": 
        "newRoot":  "$arrayToObject": "$counts" 
         
])

示例输出


    "user" : 67,
    "superuser" : 5,
    "admin" : 4,
    "moderator" : 12

【讨论】:

这不是问题的答案,但它仍然很有帮助。我想知道这与.distinct() 相比表现如何。 谢谢!完全按照我需要的方式工作。【参考方案5】:

要在集合中的 field_1 中找到不同的,但我们也想要一些 WHERE 条件,而不是像下面这样:

db.your_collection_name.distinct('field_1', WHERE condition here and it should return a document)

所以,从年龄 > 25 的集合中找到不同的数字 names

db.your_collection_name.distinct('names', 'age': "$gt": 25)

希望对你有帮助!

【讨论】:

【参考方案6】:

我使用这个查询:

var collection = "countries"; var field = "country"; 
db[collection].distinct(field).forEach(function(value)print(field + ", " + value + ": " + db[collection].count([field]: value)))

输出:

countries, England: 3536
countries, France: 238
countries, Australia: 1044
countries, Spain: 16

此查询首先区分所有值,然后计算每个值的出现次数。

【讨论】:

你能告诉我如何在 php laravel 中编写同样的查询吗? 这个查询中的主机是什么? @HeenaPatil 好收获!我在查询中有两个错误,我现在修复了它。 hosts 是我在我的数据库中收藏的名称......对此感到抱歉。我还修复的另一个问题尝试调用db.collection,我将其修复为db[collection]。谢谢!【参考方案7】:

我想要一个更简洁的答案,我使用aggregates and group 的文档提出了以下内容

db.countries.aggregate(["$group": "_id": "$country", "count":"$sum": 1])

【讨论】:

以上是关于mongodb count 每个字段/键的不同值的数量的主要内容,如果未能解决你的问题,请参考以下文章

python| MongoDB聚合(countdistinctgroupMapReduce)

MongoDB:如何为集合中的每个文档设置一个等于另一个字段值的新字段[重复]

MongoDB索引相同键的不同数据类型

如何在 mongodb 的数组中合并具有相同键的对象?

如何检索 MongoDB 上每个其他不同字段的字段最大的文档?

获取Mongodb中多个值的不同值