2017-09-28 99 views
5

Próbuję zliczyć różne wartości wielu pól za pomocą jednego zapytania o agregację MongoDB.Wyraźna liczba wielu pól przy użyciu agregacji mongodb

Więc oto moje dane:

{ 
    "car_type": "suv", 
    "color": "red", 
    "num_doors": 4 
}, 
{ 
    "car_type": "hatchback", 
    "color": "blue", 
    "num_doors": 4 
}, 
{ 
    "car_type": "wagon", 
    "color": "red", 
    "num_doors": 4 
} 

Chcę odrębny licznik poszczególnych pól:

distinct_count_car_type=3 
distinct_count_color=2 
distinct_count_num_doors=1 

udało mi się wiele pól grupy, a następnie zrobić odrębny licznik ale to może tylko dać ja liczę na pierwszym polu. Nie wszyscy z nich. A także jest to duży zestaw danych.

Odpowiedz

1

szukasz mocą ... $objectToArray!

db.foo.aggregate([ 
    {$project: {x: {$objectToArray: "$$CURRENT"}}} 
    ,{$unwind: "$x"} 
    ,{$match: {"x.k": {$ne: "_id"}}} 
    ,{$group: {_id: "$x.k", y: {$addToSet: "$x.v"}}} 
    ,{$addFields: {size: {"$size":"$y"}} } 
        ]); 

ta przyniesie:

{ "_id" : "num_doors", "y" : [ 4 ], "size" : 1 } 
{ "_id" : "color", "y" : [ "blue", "red" ], "size" : 2 } 
{ 
    "_id" : "car_type", 
    "y" : [ 
     "wagon", 
     "hatchback", 
     "suv" 
    ], 
    "size" : 3 
} 

może $project lub $addFields zgodnie z potrzebami, aby włączyć lub wyłączyć zestaw unikatowych wartości lub wielkości Ty.

+0

Niestety używam mongodb 3.2 i $ objectToArray Myślę, że zgodnie z instrukcją został wprowadzony w 3.4. – Deckard

+0

Prawidłowo. Zaleciłbym uaktualnienie do wersji 3.4.4. –

+0

Tak więc uaktualniłem i wypróbowałem twoje rozwiązanie. Problem, który mam teraz, to te dynamiczne pola, które chciałem zrobić, by były wyraźnie liczone, są w rzeczywistości w tablicy, ponieważ pochodzą z wyszukiwania $ z innej kolekcji. Kolekcja na górze pytania znajduje się w tablicy z wynikami wyszukiwania $. Tak więc, gdy próbuję wykonać $ objectToArray na polu, otrzymuję "$ objectToArray wymaga wejścia do dokumentu, znalezionego: tablica". I najpierw wypróbowałem $ arrayToObject, aby móc wywołać na nim obiekt $ objectToArray i otrzymam polecenie "$ arrayToObject wymaga kluczy obiektowych" klucza "i" v "Znaleziona niepoprawna liczba kluczy: 5". – Deckard

4

uruchamiając następującą łączną rurociągu powinno dać pożądanego rezultatu:

db.collection.aggregate([ 
    { 
     "$group": { 
      "_id": null, 
      "distinct_car_types": { "$addToSet": "$car_type" }, 
      "distinct_colors": { "$addToSet": "$color" }, 
      "distinct_num_doors": { "$addToSet": "$num_doors" } 
     } 
    }, 
    { 
     "$project": { 
      "distinct_count_car_type": { "$size": "$distinct_car_types" }, 
      "distinct_count_color": { "$size": "$distinct_colors" }, 
      "distinct_count_num_doors": { "$size": "$distinct_num_doors" } 
     } 
    } 
]) 
+0

ładne, a także możesz dodać '_id: 0' w rzucie;). –

+0

To działa. Dzięki! Spowalnia trochę, ale nie za bardzo. Być może będę musiał zadać nowe pytanie, ale co by było, gdyby obiekty te składały się z dynamicznej liczby pól (co oznacza, że ​​nie byłbym w stanie zakodować nazwy pola z wyprzedzeniem). Czy istnieje sposób na uzyskanie wyraźnej liczby na dowolnej liczbie pól w mojej mapie? Jak mogę to zrobić? – Deckard

+1

@Deckard patrz poniżej. –