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

MongoDb Pipeline Aggregation сортиране на подподдокументи

Правите грешка още от самото начало на вашия конвейер за агрегиране

$project: {
            "tasks" : 1
        }

с което губите всичките си данни. Така че първо трябва да го резервирате, като направите:

$project: {
             tasks: 1,
             doc: {
                     title: "$title", 
                     order: "$order", 
                     description: "$description", 
                     status: "$status"
                  }
          }

След това изпълнете своя $unwind както правите във въпроса си:

{$unwind: "$tasks"}, {$unwind: "$tasks.subTasks"}

След това направете сортирането. Трябва да направите сортирането със съставни ключове, в противен случай подреждането по tasks.subTasks.order няма да се задържи веднага щом сортирате по tasks.order . И така:

{$sort: {"tasks.order": -1, "tasks.subTasks.order": 1}}

И тогава идва трудната част. Трябва да $group върнете резултатите и първата стъпка е $push обратно на subTasks , но преди всичко отново трябва да запазите атрибутите на задачата:

$project: {
             doc: 1, 
             task_id: "$tasks._id", 
             tasks_doc: {
                           title: "$tasks.title", 
                           description: "$tasks.description", 
                           order: "$tasks.order", 
                           status: "$tasks.status"
                        }, 
             subTasks: "$tasks.subTasks"
          }

...съберете subTasks :

$group: {
           _id: {
                   _id: "$_id", 
                   task_id: "$task_id", 
                   doc: "$doc", 
                   task_doc: "$tasks_doc"
                }, 
           subTasks: {
                        $push: "$subTasks"
                     }
        }

И същото за tasks . Обърнете внимание, че по време на $group ing също трябва да проектирате обратно task_doc атрибути:

$group: {
           _id: {
                   _id: "$_id._id", 
                   doc: "$_id.doc"
                }, 
           tasks: {
                     $push: {
                               _id: "$_id.task_id", 
                               title: "$_id.task_doc.title", 
                               description: "$_id.task_doc.description",
                               order: "$_id.task_doc.order", 
                               status: "$_id.task_doc.status" 
                               subTasks: "$subTasks"
                            }
                  }
        }

И след това проектирайте обратно основния doc атрибути:

$project: {
             _id: "$_id._id", 
             title: "$_id.doc.title", 
             description: "$_id.doc.description", 
             order: "$_id.doc.order", 
             status: "$_id.doc.status", 
             tasks: 1
          }

Това е в общи линии. Ето пълния тръбопровод за необработено агрегиране, така че можете да тествате и да видите дали получавате желания резултат:

[
 {$match: {_id: ObjectId("554a13d4b692088a38f01f3b")}}, 
 {$project: {tasks: 1, doc: {title: "$title", order: "$order", description: "$description", status: "$status"}}}, 
 {$unwind: "$tasks"}, 
 {$unwind: "$tasks.subTasks"}, 
 {$sort: {"tasks.order": -1, "tasks.subTasks.order": 1}}, 
 {$project: {doc: 1, task_id: "$tasks._id", tasks_doc: {title: "$tasks.title", description: "$tasks.description", order: "$tasks.order", status: "$tasks.status"}, subTasks: "$tasks.subTasks"}}, 
 {$group: {_id: {_id: "$_id", task_id: "$task_id", doc: "$doc", task_doc: "$tasks_doc"}, subTasks: {$push: "$subTasks"}}}, 
 {$group: {_id: {_id: "$_id._id", doc: "$_id.doc"}, tasks: {$push: {_id: "$_id.task_id", title: "$_id.task_doc.title", description: "$_id.task_doc.description", order: "$_id.task_doc.order", status: "$_id.task_doc.status", subTasks: "$subTasks"}}}}, 
 {$project: {_id: "$_id._id", title: "$_id.doc.title", description: "$_id.doc.description", order: "$_id.doc.order", status: "$_id.doc.status", tasks: 1}}
]

АКТУАЛИЗАЦИЯ

Ако поле за масив е празно или не съществува (е null ) $unwind операция в това поле ще върне празен резултат . Решението на тази ситуация е първоначалната настройка на null /празно поле до някаква zero стойност, напр. "<empty-array>" . Имайте предвид, че трябва да направите този $project ion за всеки масив, преди неговия $unwind .

Разгледайте този отговор за това как да използвате $ifNull оператор. Вижте и $size оператор тук .

След като се справите с тази част, трябва да $group върнете резултатите и това може да се постигне с помощта на $cond оператор , за да проверите спрямо "<empty-array>" стойност




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Проектирайте като вложен документ в spring mongo

  2. MongoDB $push

  3. MongoError:връзка 0 към localhost:27017 изтече

  4. Как да изтрия вложен обект въз основа на неговия ObjectId?

  5. Страниране на масив, съхранен в поле на документ