mongodb count liczba odrębnych wartości na pole / klucz


104

Czy istnieje zapytanie do obliczenia, ile różnych wartości zawiera pole w bazie danych?

fe mam pole dla kraju i jest 8 typów wartości kraju (Hiszpania, Anglia, Francja itd.)

Jeśli ktoś doda więcej dokumentów z nowym krajem to chciałbym, żeby zapytanie zwróciło 9.

Czy jest łatwiejszy sposób niż grupowanie i liczenie?


2
Czy spojrzałeś na ramy agregacji ?
WiredPrairie


Odpowiedzi:


198

MongoDB zawiera distinctpolecenie, które zwraca tablicę odrębnych wartości dla pola; możesz sprawdzić długość tablicy pod kątem liczby.

Jest też db.collection.distinct()pomocnik powłoki :

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

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

47
to naprawdę nie działa, jeśli liczba różnych wartości jest zbyt duża ... jeśli szukałeś różnych nazw osób na świecie lub coś w tym stylu. czy masz odpowiedź, która się skaluje?
poniżej

3
1+ za długość. starałem się znaleźć coś takiego. Dzięki.
Adeel Ahmad

Nie wiem, dlaczego nie używają tam również count ()
Marian Klühspies

1
@ MarianKlühspies - ponieważ jest to po prostu tablica javascript, która używa właściwości length do zliczania liczby elementów.
UpTheCreek

Właśnie tego szukałem ... TY
Maulzey

113

Oto przykład użycia interfejsu API agregacji. Aby skomplikować sprawę, grupujemy według słów niewrażliwych na wielkość liter z właściwości tablicy dokumentu.

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

które dają wynik taki jak

{ "_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
Zalogowano się tylko po to, aby + tę odpowiedź. Dzięki! przy okazji, jeśli robisz to na unikalnym polu, po prostu usuń rozwijaną linię.
Richie Rich,

@RichieRich, unwindjest konieczne, ponieważ kod grupuje poszczególne wartości pola tablicy, które odpowiada temu, jak distinctdziała.
Paul,

@Paul Richie powiedział, że jeśli grupowanie jest wykonywane tylko w „zwykłym” polu (string, int itp.), Nie potrzebujesz kroku odwijania. Czy to nie jest poprawne?
guyarad

@guyarad unwindjest niezbędne podczas pracy z tablicami.
Paul

+1 za odpowiedź, dokładnie to, nad czym pracowałem, jakkolwiek odmienne ma swoje wdzięki ale to jest po prostu złoto :) - zresztą muszę poczytać więcej o agregatach, aby osiągnąć pożądany zestaw wyników do filtrowania danych
Talha

21

Dzięki MongoDb 3.4.4 i nowszym możesz wykorzystać $arrayToObjectoperatora i $replaceRootpotok, aby uzyskać liczby.

Na przykład załóżmy, że masz kolekcję użytkowników z różnymi rolami i chcesz obliczyć różne liczby ról. Musisz uruchomić następujący potok zagregowany:

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

Przykładowe dane wyjściowe

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

To nie jest odpowiedź na pytanie, ale mimo wszystko jest pomocna. Zastanawiam się, jak to działa w porównaniu z .distinct().
Redsandro

9

Możesz skorzystać z rozszerzeń powłoki Mongo . Jest to pojedynczy import .js, który możesz dołączyć do swojego $HOME/.mongorc.jslub programowo, jeśli kodujesz również w Node.js / io.js.

Próba

Dla każdej odrębnej wartości pola zlicza wystąpienia w dokumentach opcjonalnie filtrowane według zapytania

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

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

Parametr pola może być tablicą pól

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

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

jak zaimportować to w węźle?
Salmaan P

require("./script.js"), przypuszczam
evandrix

racja, ale nie udało mi się uzyskać funkcji w środku. Jak ich używać. Są zdefiniowane jako db.protoptype.distinctAndCount
Salmaan P

W pliku readme repozytorium znajduje się sekcja z instrukcjami (RTFM! 1 !! 1!). Zasadniczo umieść .mongorc.jsplik w katalogu domowym. Gotowe.
Janis F

6

Aby znaleźć field_1coś innego w kolekcji, ale chcemy też mieć jakiś WHEREwarunek, niż możemy zrobić, jak poniżej:

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

Więc znajdź liczbę inną namesniż zbiór, w której wiek> 25 lat będzie wyglądał następująco:

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

Mam nadzieję, że to pomoże!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.