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


104

是否存在用于计算字段在数据库中包含多少个不同值的查询。

fe我有一个国家/地区字段,并且有8种国家/地区值(西班牙,英国,法国等)。

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

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


2
您是否看过聚合框架?
WiredPrairie

1

Answers:


198

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

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

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

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

47
如果您的独特价值观的数量过多,这实际上是行不通的。。。。你有一个可以扩展的答案吗?
2014年

3
长度为1+。我正在努力寻找类似的东西。谢谢。
Adeel Ahmad 2015年

我不知道他们为什么
不在

1
@MarianKlühspies-因为它只是一个javascript数组,它使用length属性来计数元素的数量。
UpTheCreek '18

TY
Maulzey

113

这是使用聚合API的示例。为了使大小写复杂化,我们根据文档的array属性按不区分大小写的单词进行分组。

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 }

2
仅登录到+此答案。谢谢!顺便说一句,如果您要在唯一字段上执行此操作,只需删除展开线。
Richie Rich

@RichieRich unwind是必需的,因为代码正在对与distinct工作方式匹配的数组字段的各个值进行分组。
保罗

@Paul Richie所说的是,如果仅在“常规”字段(字符串,整型等)中完成了分组,则不需要展开步骤。是不是这样
Guyarad '17

unwind使用数组时,@ guyarad 是必需的。
保罗

+1是答案,正是我正在做的事情,但是与众不同有其自身的魅力,但这只是金子:)-无论如何,我必须阅读更多有关聚合的信息,以获取所需的结果集以过滤数据
Talha

21

使用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()
Redsandro

9

您可以利用Mongo Shell扩展。这是单个.js导入$HOME/.mongorc.js,如果您也使用Node.js / io.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,
  ...
}

我如何将其导入节点中?
Salmaan P

require("./script.js"),我想
evandrix

是的,但是我无法将功能包含在内。如何使用它们。它们被定义为db.protoptype.distinctAndCount
Salmaan P

回购的自述文件(RTFM!1 !! 1!)中有一个“操作方法”部分,基本上,将.mongorc.js文件放入您的主目录中。做完了
Janis F '18

6

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}})

希望能帮助到你!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.