Cóż, nie możesz tak po prostu „pogodzić się”. operatorów jako $mode
nie jest operatorem agregacji, a jedyne rzeczy, których możesz użyć, to te, które faktycznie istnieje
.
Aby więc zwrócić wartość kategorii w zgrupowanym okresie, który występuje najczęściej, należy najpierw pogrupować każdą z tych wartości i zwrócić liczbę wystąpień. Następnie możesz uporządkować te wyniki według tej liczby i zwrócić wartość kategorii, która zarejestrowała najwyższą liczbę w tym okresie:
// Filter dates
{ "$match": {
"dt": {
"$gt": new Date("October 13, 2010 12:00:00"),
"$lt": new Date("November 13, 2010 12:00:00")
}
}},
// Group by hour and category, with avg and count
{ "$group": {
"_id": {
"dt": {
"$add": [
{
"$subtract": [
{ "$subtract": ["$dt", new Date(0)] },
{
"$mod": [
{ "$subtract": ["$dt", new Date(0)] },
3600000//1000 * 60 * 60
]
}
]
},
new Date(0)
]
},
"category": "$category"
},
"price": { "$avg": "$price" },
"count": { "$sum": 1 }
}},
// Sort on date and count
{ "$sort": { "_id.dt": 1, "count": -1 }},
// Group on just the date, keeping the avg and the first category
{ "$group": {
"_id": "$_id.dt",
"price": { "$avg": "$price"}
"category": { "$first": "$_id.category" }
}}
Więc $group
zarówno dla daty, jak i kategorii i zachowaj liczbę kategorii za pośrednictwem $sum
. Następnie $sort
więc największa „liczba” jest na górze dla każdej zgrupowanej daty. I na koniec użyj $first
kiedy zastosujesz inną $group
jest to po prostu stosowane do samej daty, aby zwrócić kategorię z największą liczbą dla każdej daty.
Nie daj się skusić operatorom takim jak $max
ponieważ nie działają tutaj. Kluczową różnicą jest „związany” związek z „rekordem/dokumentem” wytworzonym dla każdej wartości kategorii. Nie chodzi więc o maksymalną „liczbę” lub maksymalną wartość „kategorii”, ale o wartość kategorii, która „wyprodukowała” największą liczbę. Stąd istnieje $sort
potrzebne tutaj.
Na koniec kilka nawyków, które „powinieneś” przełamać:
-
Nie używaj danych instancji daty w formacie innym niż UTC jako danych wejściowych, chyba że naprawdę wiesz, co robisz. Daty będą zawsze konwertowane na UTC, więc przynajmniej w zestawieniach testowych powinieneś przyzwyczaić się do określania wartości daty w ten sposób.
-
W drugą stronę może wyglądać trochę czyściej, ale rzeczy takie jak
1000 * 60 * 60
są o wiele bardziej opisowym kodem tego, co robi niż3600000
. Ta sama wartość, ale jedna forma na pierwszy rzut oka wskazuje na jednostki czasu. -
Składanie
_id
gdy istnieje tylko jedna wartość, może również mylić problemy. Więc nie ma sensu uzyskiwać dostępu do_id.dt
gdyby to była jedyna obecna wartość. Kiedy jest więcej niż jedna właściwość w_id
to jest w porządku. Ale pojedyncze wartości należy po prostu przypisać z powrotem do_id
sam. Nic nie zyskało inaczej, a singiel jest całkiem jasny.