2017-01-11 10 views
4

구조는 다소 비슷합니다. children 배열이 비어 있지 않은 경우

[ 
    {id: 1, name: "alex" , children: [2, 4, 5]}, 
    {id: 2, name: "felix", children: []}, 
    {id: 3, name: "kelly", children: []}, 
    {id: 4, name: "hannah", children: []}, 
    {id: 5, name: "sonny", children: [6]}, 
    {id: 6, name: "vincenzo", children: []} 
] 

나는 이름 children 아이디의를 교체합니다.

따라서 쿼리 결과는 다음과 같습니다.

[ {id: 1, name: "alex" , children: ["felix", "hannah" , "sonny"]} 
    {id: 5, name: "sonny", children: ["vincenzo"]} 
] 

나는 이것을 달성하기 위해 무엇을 했는가?

db.list.aggregate([ 
    {$lookup: { from: "list", localField: "id", foreignField: "children", as: "children" }}, 
    {$project: {"_id" : 0, "name" : 1, "children.name" : 1}}, 
]) 
내가
{ "name" : "alex", "parent" : [ ] } 
{ "name" : "felix", "parent" : [ { "name" : "alex" } ] } 
{ "name" : "kelly", "parent" : [ ] } 
{ "name" : "hannah", "parent" : [ { "name" : "alex" } ] } 
{ "name" : "sonny", "parent" : [ { "name" : "alex" } ] } 
{ "name" : "vincenzo", "parent" : [ { "name" : "sonny" } ] } 

내가 무엇을 잘못 이해 않았다 :) 원하는 것이 아니다 부모와

채워진 어린이?

답변

6

$lookup 단계를 사용하기 전에 어린이 배열의 경우 $unwind을 사용해야하고 어린이 배열의 경우 $lookup을 사용해야합니다. $lookup 단계 후에는 이름 대신 ID 어린이 배열을 얻을 수 $group를 사용할 필요가

당신은 그것을 시도 할 수 있습니다 :

db.list.aggregate([ 
    {$unwind:"$children"}, 
    {$lookup: { 
     from: "list", 
     localField: "children", 
     foreignField: "id", 
     as: "childrenInfo" 
     } 
    }, 
    {$group:{ 
     _id:"$_id", 
     children:{$addToSet:{$arrayElemAt:["$childrenInfo.name",0]}}, 
     name:{$first:"$name"} 
     } 
    } 
]); 

// can use $push instead of $addToSet if name can be duplicate 

$group을 사용하는 이유는 무엇입니까? 예를 들어

: 첫 번째 문서

{id: 1, name: "alex" , children: [2, 4, 5]} 

$unwind 후 문서가 $group 후 다음

{id: 1, name: "alex" , children: 2}, 
{id: 1, name: "alex" , children: 4}, 
{id: 1, name: "alex" , children: 5} 

$lookup

{id: 1, name: "alex" , children: 2, 
    "childrenInfo" : [ 
     { 
      "id" : 2, 
      "name" : "felix", 
      "children" : [] 
     } 
    ]}, 
//.... 

과 같이됩니다 당신이 $graphLookup를 사용할 수있다 현재 몽고 3.4 버전으로

{id: 1, name: "alex" , children: ["felix", "hannah" , "sonny"]} 
+1

답장을 보내 주셔서 감사합니다. 나는 localfield와 foreignField에 대한 나의 실수를 이해했다. 그러나 쿼리에서'$ group'을 설명 할 수 있습니까? – mmu36478

+0

'$ unwind' 때문에 * children * 배열은 각 children *에 대해 별도의 문서로 만들고 다시 children *의 배열을 만들기 위해'$ group'을 사용해야합니다. –

+0

각 집계 방법 후에 현재 상태를 보여준 것처럼 - 따라하기 훨씬 쉬워집니다. +1 –

3

.

$maxDepth은 비 재귀 적 조회의 경우 0으로 설정됩니다. 룩업 전에 자식이없는 레코드를 필터링하기 위해 $match 스테이지를 추가 할 수 있습니다.

db.list.aggregate([{ 
    $graphLookup: { 
     from: "list", 
     startWith: "$children", 
     connectFromField: "children", 
     connectToField: "id", 
     as: "childrens", 
     maxDepth: 0, 
    } 
}, { 
    $project: { 
     "_id": 0, 
     "name": 1, 
     "childrenNames": "$childrens.name" 
    } 
}]); 
+0

최고급 솔루션 감사합니다. – Vipul