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.