W ramach agregacji MongoDB dostępne są operatory agregacji dat. Na przykład $dayOfYear
operator służy do pobrania tej wartości od daty do użycia w grupowaniu:
db.collection.aggregate([
{ "$group": {
"_id": { "$dayOfYear": "$datetime" },
"total": { "$sum": "$count" }
}}
])
Możesz też użyć metody matematycznej opartej na datach. Stosując datę epoki, konwertujesz obiekt daty na liczbę, w której można zastosować matematykę:
db.collection.aggregate([
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$datetime", new Date("1970-01-01") ] },
{ "$mod": [
{ "$subtract": [ "$datetime", new Date("1970-01-01") ] },
1000 * 60 * 60 * 24
]}
]
},
"total": { "$sum": "$count" }
}}
])
Jeśli to, czego szukasz, to odstępy od bieżącego punktu w czasie, to tym, czego chcesz, jest zasadniczo podejście matematyczne z datą i praca z niektórymi warunkami warunkowymi za pomocą $cond
operator:
db.collection.aggregate([
{ "$match": {
"datetime": {
"$gte": new Date(new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 365 ))
}
}},
{ "$group": {
"_id": null,
"24hours": {
"$sum": {
"$cond": [
{ "$gt": [
{ "$subtract": [ "$datetime", new Date("1970-01-01") ] },
new Date().valueOf() - ( 1000 * 60 * 60 * 24 )
]},
"$count",
0
]
}
},
"30days": {
"$sum": {
"$cond": [
{ "$gt": [
{ "$subtract": [ "$datetime", new Date("1970-01-01") ] },
new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 30 )
]},
"$count",
0
]
}
},
"OneYear": {
"$sum": {
"$cond": [
{ "$gt": [
{ "$subtract": [ "$datetime", new Date("1970-01-01") ] },
new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 365 )
]},
"$count",
0
]
}
}
}}
])
Jest to zasadniczo to samo podejście, co przykład SQL, w którym zapytanie warunkowo ocenia, czy wartość daty mieści się w wymaganym zakresie i decyduje, czy dodać wartość do sumy.
Jedynym dodatkiem tutaj jest dodatkowy $match
etap, aby ograniczyć zapytanie do działania tylko na tych elementach, które prawdopodobnie mieszczą się w maksymalnym zakresie jednego roku, o który prosisz. To sprawia, że jest nieco lepszy niż prezentowany SQL, ponieważ indeks może być użyty do odfiltrowania tych wartości i nie ma potrzeby "brutalnej siły" przez niepasujące dane w kolekcji.
Zawsze dobrym pomysłem jest ograniczenie danych wejściowych za pomocą $match
podczas korzystania z potoku agregacji.