sql >> Databasteknik >  >> NoSQL >> MongoDB

$summa från dokument och underdokument grupp av $author (MongoDB)

Inte direkt synligt men möjligt. Vad du behöver göra här är att kombinera ditt dokument på högsta nivå med mängden kommentarer utan att duplicera det. Här är ett tillvägagångssätt för att först sammanfoga innehållet som två arrayer till en singulär array, sedan $unwind för att gruppera innehållet:

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 } }
])

Vilket ger utdata:

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

Även som att hoppa över den första $group steg och gör en kombinerad array på ett annat sätt:

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 } }
])

De använder operatorer som $setUnion och till och med $map som introducerades från och med MongoDB 2.6. Detta gör det enklare, men det kan fortfarande göras i tidigare versioner som saknar dessa operatörer, enligt ungefär samma principer:

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 } }
])

$const är odokumenterad men finns i alla versioner av MongoDB där aggregeringsramverket finns (från 2.2). MongoDB 2.6 introducerade $literal som i huvudsak länkar till samma underliggande kod. Det har använts i två fall här för att antingen tillhandahålla ett mallelement för en array, eller som att introducera en array för att varva ner för att ge ett "binärt val" mellan två åtgärder.



  1. Hur får jag en lista över bara ObjectId som använder pymongo?

  2. kan inte installera mongodb på ubuntu 16.10

  3. i React kallar jag två listor till sida från mongo och jag vill klicka på en för att filtrera vad som visas i andra

  4. mongod --bind_ip med docker-compose version 2