2013-03-19 16 views
6

Ich habe eine Benutzerbasis in Mongo gespeichert. Benutzer können ihr Geburtsdatum notieren. Ich muss einen Bericht aggregieren Benutzer nach Alter ausführen.Mongo Aggregation Framework: Gruppe Benutzer nach Alter

Ich habe jetzt eine Pipeline, die Benutzer nach Jahr der Geburt gruppiert. Das ist jedoch nicht präzise genug, weil die meisten Menschen nicht am 1. Januar geboren werden; Selbst wenn sie beispielsweise 1970 geboren werden, mögen sie noch nicht 43 sein.

Wissen Sie, ob es möglich ist, eine Art von Arithmetik innerhalb des Aggregation-Frameworks durchzuführen, um genau das Alter eines Benutzers zu berechnen? Oder ist das nur mit MapReduce möglich?

+0

Ich denke, '$ subtract' Betreiber ist für die Aufgabe geeignet, aber leider nicht unterstützt wird' Dates' in der aktuellen stabilen Version :) – user20140268

+0

Nun, wenn die date wird in millis gespeichert, die Lösung könnte in Subtraktion von Millisekunden (als long type) vorliegen und dann in das Date-Format konvertiert werden. – user

Antwort

8

Es scheint, wie die ganze Sache ist möglich mit der neuen Version von Mongo 2.4, die gerade veröffentlicht wurde und zusätzliche Date-Operationen unterstützt (nämlich den "$ subtract").

Hier ist, wie ich es tat:

db.Users.aggregate([ 
    { $match : { "DateOfBirth" : { $exists : true} } }, 
    { $project : {"ageInMillis" : {$subtract : [new Date(), "$DateOfBirth"] } } }, 
    { $project : {"age" : {$divide : ["$ageInMillis", 31558464000] }}}, 
    // take the floor of the previous number: 
    { $project : {"age" : {$subtract : ["$age", {$mod : ["$age",1]}]}}}, 
    { $group : { _id : "$age", Total : { $sum : 1} } }, 
    { $sort : { "Total" : -1 } } 
]) 
+0

ist nicht das '%' in "new Date()%" ein Tippfehler? Übrigens, tolle Antwort. – joao

+0

Hm, geht aber nicht mit Schaltjahren um, soweit ich das beurteilen kann. Wie wäre es, so etwas zu integrieren? –

+0

Funktion IsLeap (Jahr) { Rückgabe Jahr% 4 == 0 && (Jahr% 100! = 0 || Jahr% 400 == 0); } –

1

Es gibt nicht genug dateTime-Operatoren und mathematische Operatoren, um das Datum zu projizieren. Aber Sie könnten in der Lage Altersstufen zu schaffen, indem eine dynamische Abfrage Komponieren:

Definieren Sie Ihre Datumsbereiche als Stichtag als

DT18 = heute - 18 DT25 = heute - 25 ... DT65 = heute - 65

Dann verschachtelte Bedingungen zu tun, wo man schrittweise die abgeschnittenen Termine als Altersgruppe Marker verwenden, etwa so:

db.folks.save({ "_id" : 1, "bd" : ISODate("2000-02-03T00:00:00Z") }); 
db.folks.save({ "_id" : 2, "bd" : ISODate("2010-06-07T00:00:00Z") }); 
db.folks.save({ "_id" : 3, "bd" : ISODate("1990-10-20T00:00:00Z") }); 
db.folks.save({ "_id" : 4, "bd" : ISODate("1964-09-23T00:00:00Z") }); 


db.folks.aggregate(
    { 
    $project: { 
     ageGroup: { 
      $cond: [{ 
       $gt: ["$bd", 
       ISODate("1995-03-19")] 
      }, 
      "age0_18", 
      { 
       $cond: [{ 
        $gt: ["$bd", 
        ISODate("1988-03-19")] 
       }, 
       "age18_25", 
       "age25_plus"] 
      }] 
     } 
    } 
}, 
{ 
    $group: { 
     _id: "$ageGroup", 
     count: { 
      $sum: 1 
     } 
    } 
}) 
Verwandte Themen