mongodb підраховує кількість різних значень на поле / ключ


104

Чи є запит для обчислення кількості різних значень, яке містить поле в БД.

fe У мене є поле для країни і є 8 типів значень країни (Іспанія, Англія, Франція тощо)

Якщо хтось додасть більше документів у новій країні, я хотів би, щоб запит повернувся 9.

Чи є простіший спосіб, ніж згрупуватись і порахувати?


2
Ви подивилися на рамки агрегації ?
WiredPrairie


Відповіді:


198

MongoDB має distinctкоманду, яка повертає масив різних значень для поля; ви можете перевірити довжину масиву для підрахунку.

Також є db.collection.distinct()помічник снарядів :

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

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

47
це насправді не спрацьовує, якщо ваша кількість різних значень занадто велика ... якщо ви дивилися на окремі імена людей у ​​світі чи щось таке. у вас є відповідь, що ваги?
недоріг

3
1+ для довжини. я намагався знайти щось подібне. Дякую.
Адель Ахмед

Я не знаю, чому вони теж не використовують count ()
Marian Klühspies

1
@ MarianKlühspies - тому що це лише масив javascript, який використовує властивість length для підрахунку кількості елементів.
UpTheCreek

Тільки те, що я шукав ... TY
Maulzey

113

Ось приклад використання агрегаційного 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 }

2
Увійшли лише до + цієї відповіді. Дякую! btw, якщо ви робите це на унікальному полі, просто видаліть розмотану лінію.
Річі Річ

@RichieRich, unwindнеобхідний тому, що код групує окремі значення поля масиву, які відповідають тому, як distinctпрацює.
Павло

@Paul, що сказав Річі, це те, що якщо групування виконується просто "звичайним" полем (рядок, int і т. Д.), То вам не потрібен крок розмотування. Чи не правильно?
гуярад

@guyarad unwindнеобхідний при роботі з масивами.
Павло

+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().
Редсандро

9

Ви можете скористатися розширенням Shell Mongo . Це один імпорт .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,
  ...
}

як би я імпортував це у вузол?
Salmaan P

require("./script.js"), я гадаю
evandrix

правильно, але я не зміг отримати функції всередині. Як я ними користуюся. Вони визначені як db.protoptype.distinctAndCount
Salmaan P

У розділі репортажу РЕПО (RTFM! 1 !! 1!) В основному є вміст .mongorc.jsфайлу , помістіть файл у ваш домашній dir. Зроблено.
Janis F

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

Сподіваюся, це допомагає!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.