2013-02-20 16 views
16

Dla jednej z moich kolekcji, która musi pozostać uniksowym znacznikiem czasu zamiast izodatu, zwykle konwertuję znacznik czasu z nową datą (unix_timestamp).

Teraz potrzebuję agregacji new Date(ts). (Przykładem jest w PHP)

'$ projekt' => array ('dzień' => '$ new Date (ts)', ...

'$ grupa' => array ("_id" => array ('dzień' => '$ day)', ...), ...

nie dociera do wyników. Brak pola "dzień" w wyniku

Jak przekonwertować tę wartość w ramach agregacji?

Odpowiedz

3

Dla reklamy Dodatkowy pola wyliczone w projekcji trzeba użyć $ dodać operatora, na przykład: (przykład konsoli)

db.so.aggregate([{$project: {date: {$add: Date() }}}]) 

ale to źle, a my się komunikat o błędzie:

exception: $add does not support strings (or dates) 

Ale znalazłem prosty siekać =)

db.so.aggregate([{$project: {date: {$substr: [Date(), 0, -1] }}}]) 

w tym przypadku będziemy mieli oczekiwany rezultat z datami również w wyjście PHP widać błąd tak:

exception: disallowed field type Date in object expression (at 'date') 

A teraz rozwiązanie (PHP 5.4 składnia):

$so->aggregate([ 
    ['$project' => ["date" => ['$substr' => [new MongoDate(), 0, -1]] ] ] 
]); 
+2

to nie konwertuje wartości pola ts na data mongo. Przyjmuje tylko ciąg PHP lub numer jako dane wejściowe, a nie wartość z samej kolekcji:/ – ledy

+0

Ops, przepraszam) Czy w tym przypadku może być konieczne użycie opcji map-reduce zamiast aggregation? –

+0

@KirillZorin, jest genialny! substr jest idealny do wyświetlania tylko daty, upuszczając część czasu. To jest bardzo pomocne!! –

21

aby móc dodać pola datownika z dokumentu, można to zrobić, biorąc pod uwagę:

{"ts": 1400512120100} 

agregować jako datę:

db.foo.aggregate({ 
    $project: { 
     date: { $add: [new Date(0), "$ts"] } 
    } 
}) 
+1

To bardzo mi pomogło! Moje znaczniki czasu są w UTC i chciałem przekonwertować na czas lokalny. Udało mi się to zrobić przy użyciu tego podejścia. {$ project: {dd: {$ add: [nowa data (0), {$ odejmij: [{$ mnożnik: ["$ items.ordered", 1000]}, tzoffset]}]}, ... –

+1

Widzę, że to działa, ale co tu się dzieje? Po prostu '> new Date (1400512120100)' wyniki, poprawnie, w 'ISODate (" 2014-05-19T15: 08: 40.100Z ")'. Ale jeśli spróbujesz użyć 'new Date()' w '$ project' bez' $ add', otrzymasz 'niedozwolony typ pola Date in object expression'. W tym przykładzie można jednak zwrócić wyraźne daty. Jeśli spróbujesz '$ add: [new Date (" $ ts ")]' w '$ project', otrzymasz duży ujemny rok (' ISODate ("- 292275055-05-16T16: 47: 03.192Z") '). W jaki sposób '$ add' obsługuje poprawnie typy danych i zwraca' ISODate' bez błędu? – duozmo

+0

@duozmo: Myślę, że powodem, dla którego po prostu 'new Date()' nie działa jest to, że 'new Date()' jest wykonywane tylko raz, zanim rozpocznie się potok.Tylko specjalni "operatorzy agregacji" MongoDB (jak '$ add',' $ trunc' itd.) Będą działać dla każdej wartości. Dlatego jeśli chcesz utworzyć datę podczas agregacji, musisz użyć jednego z tych operatorów. Ponieważ w MongoDB nie ma operatora 'millisecondsToDate', musisz (ab) użyć' $ add'. – sleske