sql >> Database teknologi >  >> NoSQL >> MongoDB

$sum fra dokumenter og underdokumentgruppe af $author (MongoDB)

Ikke umiddelbart synligt, men muligt. Det, du skal gøre her, er at kombinere dit dokument på øverste niveau med rækken af ​​kommentarer uden at duplikere det. Her er en tilgang til først at forbinde indholdet som to arrays i en ental array, derefter $unwind for at gruppere indholdet:

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

Hvilket giver output:

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

Selv som at springe den første $group iscenesætte og gøre et kombineret array på en anden måde:

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

Disse bruger operatører såsom $setUnion og endda $map som blev introduceret fra MongoDB 2.6. Dette gør det enklere, men det kan stadig gøres i tidligere versioner, der mangler disse operatører, efter stort set de samme principper:

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 er udokumenteret, men til stede i alle versioner af MongoDB, hvor aggregeringsrammerne er til stede (fra 2.2). MongoDB 2.6 introduceret $literal som i det væsentlige linker til den samme underliggende kode. Det er blevet brugt i to tilfælde her til enten at give et skabelonelement til et array eller som at introducere et array til at slappe af for at give et "binært valg" mellem to handlinger.



  1. Samarbejde MongoDB doven indlæsning med Jackson @JsonIgnore i SpringBoot Rest Controller

  2. Hvordan får man alle de værdier, der indeholder en del af en streng, ved hjælp af mongoose find?

  3. MongoDB Node check om objectid er gyldigt

  4. Lagring af array med Doctrine og MongoDB