137

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

我有一个国家字段,有 8 种国家值(西班牙、英国、法国等)

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

有没有比分组和计数更简单的方法?

4

7 回答 7

252

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

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

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

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

如 MongoDB 文档中所述:

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

于 2013-02-18T02:43:04.980 回答
140

这是使用聚合 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 }
于 2015-10-29T15:37:24.257 回答
27

使用 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
}
于 2018-02-08T22:37:09.973 回答
10

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

样本

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

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

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

field 参数可以是一个字段数组

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

{
  "Austin,Educator" : 1,
  "Aurelia,Educator" : 1,
  "Augustine,Carpenter" : 1,
  ...
}
于 2015-05-13T13:03:24.017 回答
7

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

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

因此,找到与names年龄 > 25 的集合不同的数字:

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

希望能帮助到你!

于 2018-02-23T05:45:00.467 回答
5

我使用这个查询:

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

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

于 2020-10-25T12:58:12.593 回答
5

我想要一个更简洁的答案,我使用聚合和组中的文档想出了以下内容

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

于 2021-02-15T19:54:38.217 回答