1

Betrachtet man diese Dokumente:MongoDB Gruppendokumente und begrenzen jede Gruppe

{ 
    "Field1":"Test_1", 
    "Speaker":1, 
    "Listener":2, 
    "ListenTime": ISODate("2016-10-15T14:17:49.336Z") 
}, 
{ 
    "Field1":"Test_2", 
    "Speaker":1, 
    "Listener":2, 
    "ListenTime": ISODate("2016-10-13T14:17:49.336Z") 
}, 
{ 
    "Field1":"Test_3", 
    "Speaker":1, 
    "Listener":3, 
    "ListenTime": ISODate("2016-10-10T14:10:49.336Z") 
} 

Was ich was mit einer einzigen Abfrage in MongoDB (3.2) nur die Dokumente zu tun ist, extrahieren sie von Sprecher und Hörer Gruppierung, wobei nur das Dokument mit der ältesten ListenTime.
Also, in diesem Fall wird das Ergebnis sein:

{ 
    "Field1":"Test_1", 
    "Speaker":1, 
    "Listener":2, 
    "ListenTime": ISODate("2016-10-15T14:17:49.336Z") 
}, 
{ 
    "Field1":"Test_3", 
    "Speaker":1, 
    "Listener":3, 
    "ListenTime": ISODate("2016-10-10T14:10:49.336Z") 
} 

Ist es möglich, mit einer einzigen Abfrage zu tun?

+0

Bitte nach, was hast du es bisher versucht? –

Antwort

1

Führen Sie die folgende Aggregation Pipeline um das gewünschte Ergebnis zu erhalten:

db.collection.aggregate([ 
    { "$sort": { "ListenTime": -1 } }, 
    { 
     "$group": { 
      "_id": { 
       "Speaker": "$Speaker", 
       "Listener": "$Listener" 
      }, 
      "Field1" : { "$first": "$Field1" }, 
      "ListenTime" : { "$first": "$ListenTime" } 
     } 
    }, 
    { 
     "$project": { 
      "Field1": 1, 
      "Speaker": "$_id.Speaker", 
      "Listener": "$_id.Listener", 
      "ListenTime": 1, 
      "_id": 0 
     } 
    } 
]) 

Beispielausgabe

/* 1 */ 
{ 
    "Field1" : "Test_3", 
    "ListenTime" : ISODate("2016-10-10T14:10:49.336Z"), 
    "Speaker" : 1, 
    "Listener" : 3 
} 

/* 2 */ 
{ 
    "Field1" : "Test_1", 
    "ListenTime" : ISODate("2016-10-15T14:17:49.336Z"), 
    "Speaker" : 1, 
    "Listener" : 2 
} 
1

Das Aggregations-Framework kann dazu verwendet werden. In der ersten Stufe verwenden Sie $group, um die Dokumente nach Speaker und Listener zu gruppieren. Fügen Sie in dieser Phase alle Dokumente in der Gruppe mithilfe des Operators $push zu einer Liste hinzu, und berechnen Sie mit dem Operator $max die aktuelle ListenTime. Folgen Sie diesem Schritt, indem Sie eine $redact Bühne verwenden, um das Dokument mit der aktuellen ListenTime in der Liste zu behalten. Verwenden Sie dann eine $unwind Bühne, um die Liste in Dokumente zu reduzieren. Verwenden Sie dann eine letzte Bühne, um die gewünschten Felder zu erhalten.

Die Aggregationsabfrage sieht so aus.

db.sampleCollection.aggregate([ 
    { 
     "$group":{ 
      "_id":{"Speaker":"$Speaker", "Listener":"$Listener"}, 
      ListenTime : {"$max":"$ListenTime"}, 
      "docs":{"$push":"$$ROOT"} 
     } 
    }, 
    { 
     $redact:{ 
      $cond:[{$eq:["$ListenTime","$$ROOT.ListenTime"]},"$$DESCEND","$$PRUNE"] 
     } 
    }, 

    { 
     "$project":{ 
      "ListenTime":1, 
      "Field1":"$docs.0.Field1", 
      "Speaker":"$docs.0.Speaker", 
      "Listener":"$docs.0.Listener" 
     } 
    } 
]) 

Beispielausgabe:

{ 
     "ListenTime" : ISODate("2016-10-10T14:10:49.336Z"), 
     "Field1" : "Test_3", 
     "Speaker" : 1, 
     "Listener" : 3 
} 
{ 
     "ListenTime" : ISODate("2016-10-15T14:17:49.336Z"), 
     "Field1" : "Test_1", 
     "Speaker" : 1, 
     "Listener" : 2 
}