2016-06-13 16 views
4

Angenommen wir einige Dokumente, wie folgend haben:Abfrage Dokument mit dem max Unterfeld

{ 
    "_id": { 
    "title": "ABC", 
    "version": 1 
    }, 
    "status": "Submitted", 
    .... 
} 

{ 
    "_id": { 
    "title": "ABC", 
    "version": 2 
    }, 
    "status": "Submitted", 
    .... 
} 

{ 
    "_id": { 
    "title": "XYZ", 
    "version": 1 
    }, 
    "status": "Submitted", 
    .... 
} 

Wie kann ich die Dokumente mit dem max version für jeden verschiedenen title bekommen?

Für den Datensatz oben, sollte das Ergebnis sein:

{ 
    "_id": { 
    "title": "ABC", 
    "version": 2 
    }, 
    "status": "Submitted", 
    .... 
} 

{ 
    "_id": { 
    "title": "XYZ", 
    "version": 1 
    }, 
    "status": "Submitted", 
    .... 
} 

Antwort

5

Die Idee hier ist, die Dokumente durch den Schlüssel version zuerst zu bestellen, gruppieren Sie die Dokumente durch den Schlüssel title und geben Sie das erste Dokument in der Gruppe zurück, wenn Sie bestellt werden. Also, die eingeladen Betreiber der Aggregation Pipeline zeigen hier wird das die $sort, $group und $project (die die aggregierten Dokumente umformt in dem gewünschten Ergebnis Schema sein).

Jetzt im $group Pipeline würden Sie die $first Betreiber benötigen (oder $last abhängig von der Richtung, die Sie die Dokumente in der vorherigen $sort Pipeline bestellt) das oberste Dokument Feld zur Karte bei Bestellung .

Betrachten Sie das folgende Spiel in Mongo Mantel:

db.collection.aggregate([ 
    { "$sort": { "_id.version": -1 } }, 
    { 
     "$group": { 
      "_id": "$_id.title", 
      "id": { "$first": "$_id" }, 
      "status": { "$first": "$status" } 
      ... 
     } 
    }, 
    { 
     "$project": { 
      "_id": "$id", 
      "status": 1, 
      ... 
     } 
    } 
]) 

Für die mongoTemplate Äquivalent:

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; 

Aggregation agg = newAggregation(
    sort(DESC, "_id.version"), 
    group("_id.title"), 
     .first("status").as("status") 
     ... 
    project("id").previousOperation().and("status").and(...) 
); 

Sie haben eine andere Alternative des $$ROOT System einladen Variable zu Ihrem $group Pipeline als Mittel zum Zurückgeben des vollständigen Dokuments. Betrachten Sie den folgenden Ansatz:

db.collection.aggregate([ 
    { "$sort": { "_id.version": -1 } }, 
    { 
     "$group": { 
      "_id": "$_id.title",    
      "doc": { "$first": "$$ROOT" } 
     } 
    }, 
    { 
     "$project": { 
      "_id": "$doc._id", 
      "status": "$doc.status", 
      ... 
     } 
    } 
]) 

, die

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; 

Aggregation agg = newAggregation(
    sort(DESC, "_id.version"), 
    group("_id.title"), 
     .first(ROOT).as("doc") 
    project("doc.status").as("status")... 
); 
übersetzen würde
1

Versuchen $max verwenden.

Gibt den Maximalwert zurück. $ max vergleicht sowohl den Wert als auch den Typ und verwendet die angegebene BSON-Vergleichsreihenfolge für Werte verschiedener Typen.

können Sie folgende Abfrage verwenden: -

aggregate(
[ 
{ 
    $project: 
    { 
     _id: "$_id.title", 
     version: { $max: "$_id.version" }, 
     status : "$status" 
    } 
} 
]) 

ich die Abfrage nicht ausprobiert habe. Lassen Sie mich wissen, wenn Sie einen Fehler bekommen.

Hoffe, das wird helfen.