MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

$sum от документи и поддокументи група от $author (MongoDB)

Не се вижда веднага, но е възможно. Това, което трябва да направите тук, е да комбинирате своя документ от най-високо ниво с масива от коментари, без да го дублирате. Ето един подход първо да обедините съдържанието като два масива в единичен масив, след което $unwind за групиране на съдържанието:

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

Което дава резултата:

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

Дори при пропускане на първия $group етап и създаване на комбиниран масив по различен начин:

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

Те използват оператори като $setUnion и дори $map които бяха въведени от MongoDB 2.6. Това го прави по-просто, но все още може да се направи в по-ранни версии без тези оператори, следвайки почти същите принципи:

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 е недокументиран, но присъства във всички версии на MongoDB, където присъства рамката за агрегиране (от 2.2). MongoDB 2.6 Представен $literal което по същество се свързва със същия основен код. Използван е в два случая тук или за предоставяне на шаблонен елемент за масив, или за въвеждане на масив за разгъване, за да се осигури „двоичен избор“ между две действия.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Използване на $in в MongooseJS с вложени обекти

  2. Импортирайте данни във вашите новосъздадени екземпляри на MongoDB

  3. Има ли причини, поради които трябва/не трябва да използвам ObjectId в моя RESTful URL адрес

  4. MongoDB конфигурация в CakePHP 3.x

  5. Decimal / Float в mongoose за node.js