2017-03-08 28 views
0

用例如下。使用MongoDB的新聚合框架進行更深入的遞歸搜索

設備已通過DEVICE_ID

每個組件鏈接零個或多個組件已經通過PARENT_ID

預期結果掛鉤它自己的組件:

[ 
    { 
    id: 1 
    name: "device_a", 
    components: [ 
     { 
     name: "component_a", 
     id: 2 
     device_id: 1 
     components: [ 
      { 
       name: "component_b" 
       parent_id: 2 
       id: 3 
      } 
     ] 
     } 
    ] 
    } 
] 

使用新的聚合框架,我可以遞歸地獲得設備組件的深度1結果。 (備註:PARENT_ID爲空,指示組件不具有父組件

db.device.aggregate(
    [ 
     { "$graphLookup": { 
      "from": "component", 
      "startWith": "$_id", 
      "connectFromField": "_id", 
      "connectToField": "device_id", 
      "as": "components", 
      "restrictSearchWithMatch": { "parent_id": null } 
     }}, 
     { "$addFields": { 
      "components": { 
       "$reverseArray": "$components" 
      } 
     }} 
    ] 
) 

此查詢原來的輸出。

[ 
    { 
    id: 1 
    name: "device_a", 
    components: [ 
     { 
     name: "component_a", 
     id: 2 
     device_id: 1 
     } 
    ] 
    } 
] 

基本上,我也可以聚合組件本身,並獲得其子組件的邏輯相同的列表。

db.component.aggregate(
    [ 
     { "$match": { "parent_id": null } }, 
     { "$graphLookup": { 
      "from": "component", 
      "startWith": "$_id", 
      "connectFromField": "_id", 
      "connectToField": "parent_id", 
      "as": "components" 
     }}, 
     { "$addFields": { 
      "components": { 
       "$reverseArray": "$components" 
      } 
     }} 
    ] 
) 

/* turns out */ 

[ 
    { 
    name: "component_a", 
    id: 2 
    device_id: 1 
    components: [ 
     { 
     name: "component_b", 
     parent_id: 2 
     id: 3 
     } 
    ] 
    } 
] 

有沒有什麼好的方法將它們結合在一起?對於更高級的使用情況下,怎麼能去更多的更深,像component_a - > component_b - > component_c ...

+0

你的問題很難理解。你在做什麼?預期的結果是什麼? – styvane

回答

0

我想我可以生成形狀的東西,雖然它的複雜...

> db.devices.find() 
{ "_id" : 1, "name" : "device_a", "component_ids" : [ 2, 4 ] } 
> db.components.find().sort({parent_id: 1}) 
{ "_id" : 2, "name" : "component_a", "device_id" : 1 } 
{ "_id" : 4, "name" : "component_e", "device_id" : 1 } 
{ "_id" : 3, "name" : "component_b", "parent_id" : 2 } 
{ "_id" : 0, "name" : "component_c", "parent_id" : 2 } 
{ "_id" : 1, "name" : "component_d", "parent_id" : 3 } 
{ "_id" : 5, "name" : "component_f", "parent_id" : 4 } 
> function getFilterForDepth(i) { return {$filter: {input: "$components.sub_components", cond: {$eq: ["$$this.depth", NumberLong(i)]}}}; } 
> getFilterForDepth(0) 
{ 
    "$filter" : { 
     "input" : "$components.sub_components", 
     "cond" : { 
      "$eq" : [ 
       "$$this.depth", 
       NumberLong(0) 
      ] 
     } 
    } 
} 
> db.devices.aggregate([ 
     { 
     $lookup: { 
      from: "components", 
      localField: "component_ids", 
      foreignField: "_id", 
      as: "components" 
     } 
    }, 
    {$unwind: "$components"}, 
    {$match: {"components.parent_id": null}}, 
    { 
     $graphLookup: { 
      from: "components", 
      startWith: "$components._id", 
      connectFromField: "_id", 
      connectToField: "parent_id", 
      as: "components.sub_components", 
      depthField: "depth", 
      maxDepth: 2 
     } 
    }, 
    { 
     $addFields: { 
      "components.components": { 
       $map: { 
        input: getFilterForDepth(0), 
        in : { 
         _id: "$$this._id", 
         name: "$$this.name", 
         components: { 
          $map: { 
           input: getFilterForDepth(1), 
           in : {_id: "$$this._id", name: "$$this.name"} 
          } 
         } 
        } 
       } 
      } 
     } 
    }, 
    {$project: {"components.sub_components": 0}}, 
    {$group: {_id: "$_id", name: {$first: "$name"}, components: {$push: "$components"}}} 
]) 
.pretty(); 
{ 
    "_id" : 1, 
    "name" : "device_a", 
    "components" : [ 
     { 
      "_id" : 2, 
      "name" : "component_a", 
      "device_id" : 1, 
      "components" : [ 
       { 
        "_id" : 0, 
        "name" : "component_c", 
        "components" : [ 
         { 
          "_id" : 1, 
          "name" : "component_d" 
         } 
        ] 
       }, 
       { 
        "_id" : 3, 
        "name" : "component_b", 
        "components" : [ 
         { 
          "_id" : 1, 
          "name" : "component_d" 
         } 
        ] 
       } 
      ] 
     }, 
     { 
      "_id" : 4, 
      "name" : "component_e", 
      "device_id" : 1, 
      "components" : [ 
       { 
        "_id" : 5, 
        "name" : "component_f", 
        "components" : [ ] 
       } 
      ] 
     } 
    ] 
} 

這隻會工作到一定的深度(我做了2次,因爲它更容易),並且不是自然可擴展的,但似乎有竅門。