MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

MongoDb Pipeline Aggregation sortowanie poddokumentów

Popełniasz błąd od samego początku procesu agregacji

$project: {
            "tasks" : 1
        }

przez co tracisz wszystkie swoje dane. Więc przede wszystkim musisz zarezerwować to robiąc:

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

Następnie wykonaj $unwind tak jak w swoim pytaniu:

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

Następnie dokonaj sortowania. Musisz wykonać sortowanie za pomocą kluczy złożonych, w przeciwnym razie uporządkowanie według tasks.subTasks.order nie zostanie wstrzymane, gdy tylko posortujesz według tasks.order . A więc:

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

A potem przychodzi najtrudniejsza część. Musisz $group cofnij wyniki, a pierwszym krokiem jest $push cofnij subTasks , ale przede wszystkim musisz zachować atrybuty zadania:

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

...zbierz subTasks :

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

To samo dotyczy tasks . Zwróć uwagę, że podczas $group W tym przypadku musisz również rzutować z powrotem task_doc atrybuty:

$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"
                            }
                  }
        }

A następnie rzutuj z powrotem katalog główny doc atrybuty:

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

To w zasadzie to. Oto pełny surowy potok agregacji, dzięki czemu możesz przetestować i zobaczyć, czy uzyskasz pożądany wynik:

[
 {$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}}
]

AKTUALIZUJ

Jeśli pole tablicy jest puste lub nie istnieje (jest null ) $unwind operacja na tym polu zwróci pusty wynik . Rozwiązaniem tej sytuacji jest wstępne ustawienie null /puste pole do jakiegoś zero wartość, np. "<empty-array>" . Zauważ, że musisz zrobić ten $project jon dla każdej tablicy, przed jej $unwind .

Spójrz na tę odpowiedź o tym, jak używać $ifNull operator. Sprawdź także $size operator tutaj .

Po uporaniu się z tą częścią, musisz $group wstecz wyniki i można to osiągnąć za pomocą $cond operator , aby sprawdzić z "<empty-array>" wartość




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Pole agregatu MongoDB w tablicy obiektów

  2. NoClassDefFoundError po wyeksportowaniu jar

  3. Wykonanie JavaScript nie powiodło się połączone z powłoką mongoHQ

  4. Jak skonfigurować nazwę kolekcji MongoDb dla klasy w Spring Data?

  5. jak dodać wartość na górze tablicy w mongodb?