MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

$sum aus der Gruppe Dokumente und Unterdokumente von $author (MongoDB)

Nicht sofort sichtbar aber möglich. Was Sie hier tun müssen, ist, Ihr Dokument der obersten Ebene mit der Reihe von Kommentaren zu kombinieren, ohne es zu duplizieren. Hier ist ein Ansatz, um den Inhalt zuerst als zwei Arrays zu einem einzigen Array zusammenzufügen, dann $unwind um den Inhalt zu gruppieren:

db.collection.aggregate([
    { "$group": {
        "_id": "$_id",
        "author": { 
            "$addToSet": {
                "id": "$_id",
                "author": "$author",
                "votes": "$votes"
            }
        },
        "comments": { "$first": "$comments" }
    }},
    { "$project": {
        "combined": { "$setUnion": [ "$author", "$comments" ] }
    }},
    { "$unwind": "$combined" },
    { "$group": {
        "_id": "$combined.author",
        "votes": { "$sum": "$combined.votes" }
    }},
    { "$sort": { "votes": -1 } }
])

Was die Ausgabe ergibt:

{ "_id" : "Jesse", "votes" : 148 }
{ "_id" : "Mirek", "votes" : 135 }
{ "_id" : "Leszke", "votes" : 13 }

Sogar beim Überspringen des ersten $group Stufe und Erstellen eines kombinierten Arrays auf andere Weise:

db.collection.aggregate([
    { "$project": {
        "combined": { 
            "$setUnion": [
                { "$map": {
                    "input": { "$literal": ["A"] },
                    "as": "el",
                    "in": { 
                        "author": "$author",
                        "votes": "$votes"
                    }
                }},
                "$comments"
            ] 
        }
    }},
    { "$unwind": "$combined" },
    { "$group": {
        "_id": "$combined.author",
        "votes": { "$sum": "$combined.votes" }
    }},
    { "$sort": { "votes": -1 } }
])

Diese verwenden Operatoren wie $setUnion und sogar $map die ab MongoDB 2.6 eingeführt wurden. Das macht es einfacher, aber es kann immer noch in früheren Versionen durchgeführt werden, denen diese Operatoren fehlen, und zwar nach den gleichen Prinzipien:

db.collection.aggregate([
    { "$project": {
        "author": 1,
        "votes": 1,
        "comments": 1,
        "type": { "$const": ["A","B"] }
    }},
    { "$unwind": "$type" },
    { "$unwind": "$comments" },
    { "$group": { 
        "_id": {
          "$cond": [
              { "$eq": [ "$type", "A" ] },
              { 
                  "id": "$_id", 
                  "author": "$author",
                  "votes": "$votes"
              },
              "$comments"
          ]
        }
    }},
    { "$group": {
        "_id": "$_id.author",
        "votes": { "$sum": "$_id.votes" }
    }},
    { "$sort": { "votes": -1 } }
])

Der $const ist undokumentiert, aber in allen Versionen von MongoDB vorhanden, in denen das Aggregationsframework vorhanden ist ( ab 2.2 ). MongoDB 2.6 eingeführt $literal die im Wesentlichen mit demselben zugrunde liegenden Code verknüpft ist. Es wurde hier in zwei Fällen verwendet, um entweder ein Vorlagenelement für ein Array bereitzustellen oder um ein Array zum Entladen einzuführen, um eine "binäre Wahl" zwischen zwei Aktionen bereitzustellen.