2016-11-07 148 views
1

首先我知道這篇文章https://docs.mongodb.com/v3.2/applications/data-models-tree-structures/如何在MongoDB中存儲/檢索樹結構?

但是我需要檢索多層次的樹結構。 例如,對於數據:

{ doc: "a", children: ["b", "c"] } 
{ doc: "b", children: ["d"] } 
{ doc: "c", children: ["e"] } 
{ doc: "d", children: [] } 
{ doc: "e", children: ["f"] } 
{ doc: "f", children: [] } 

我需要檢索文檔的 「」 全樹:

a 
b 
    d 
c 
    e 
    f 

是否有可能在MongoDB中?

+1

我認爲你需要更清楚 –

+0

對於給定的文件,我想檢索所有的孩子以及每個孩子的孩子等等。 – user606521

+0

你的遍歷順序問題,即abdcef?或者它也可以是acefbd? – sergiuz

回答

1

因爲MongoDB的3.4可以使用$ graphLookup

該階段將一個文檔的connectFromField與集合中其他文檔的connectToField相匹配。然後,對於任何匹配的文件中,$ graphLookup使用匹配的文件,以匹配到的connectFromField其他文件的connectToField,並一直持續到沒有新的文件都遇到或到指定深度

https://docs.mongodb.com/master/release-notes/3.4-reference/#pipe._S_graphLookup

1

您可以嘗試黑客使用的$lookup$unwind運營商如下聚合管道:

db.collection.aggregate([ 
    { 
     "$unwind": { 
      "path": "$children", 
      "preserveNullAndEmptyArrays": true 
     } 
    }, 
    { 
     "$lookup": { 
      "from": "test", 
      "localField": "children", 
      "foreignField": "doc", 
      "as": "child" 
     } 
    }, 
    { 
     "$unwind": { 
      "path": "$child", 
      "preserveNullAndEmptyArrays": true 
     } 
    }, 
    { 
     "$unwind": { 
      "path": "$child.children", 
      "preserveNullAndEmptyArrays": true 
     } 
    },  
    { 
     "$lookup": { 
      "from": "test", 
      "localField": "child.children", 
      "foreignField": "doc", 
      "as": "child.child" 
     } 
    }, 
    { 
     "$unwind": { 
      "path": "$child.child", 
      "preserveNullAndEmptyArrays": true 
     } 
    }, 
    { 
     "$unwind": { 
      "path": "$child.child.children", 
      "preserveNullAndEmptyArrays": true 
     } 
    }, 
    { 
     "$lookup": { 
      "from": "test", 
      "localField": "child.child.children", 
      "foreignField": "doc", 
      "as": "child.child.child" 
     } 
    }, 
    { 
     "$unwind": { 
      "path": "$child.child.child", 
      "preserveNullAndEmptyArrays": true 
     } 
    }, 
    { 
     "$unwind": { 
      "path": "$child.child.child.children", 
      "preserveNullAndEmptyArrays": true 
     } 
    },  
    { 
     "$group": { 
      "_id": "$doc", 
      "children": { "$push": "$child" } 
     } 
    }, 
    { "$match": { "_id": "a" } } 
]) 

樣本輸出

{ 
    "_id" : "a", 
    "children" : [ 
     { 
      "_id" : ObjectId("58204f0cd3cda4b4b1adadfb"), 
      "doc" : "b", 
      "children" : "d", 
      "child" : { 
       "_id" : ObjectId("58204f0cd3cda4b4b1adadfd"), 
       "doc" : "d" 
      } 
     }, 
     { 
      "_id" : ObjectId("58204f0cd3cda4b4b1adadfc"), 
      "doc" : "c", 
      "children" : "e", 
      "child" : { 
       "_id" : ObjectId("58204f0cd3cda4b4b1adadfe"), 
       "doc" : "e", 
       "children" : "f", 
       "child" : { 
        "_id" : ObjectId("58204f0cd3cda4b4b1adadff"), 
        "doc" : "f" 
       } 
      } 
     } 
    ] 
} 
+0

這不適用於3級以上的樹嗎? – sergiuz

+0

它適用於儘可能多的樹級別,只需包含相應的'$ lookup'和'$ unwind'管道就可以獲得所需的結構,儘管您可能會面臨許多管道的某些性能損失 – chridam

+0

不幸的是,我不知道有多深是樹... – user606521