Home > Software design >  MongoDB get all descendants
MongoDB get all descendants

Time:08-13

I am building an application to show tree structures via jstree. The data is stored in flat array format like the following.

{id:1,text:"Parent",xpath:"/Parent",parent:"#",children:true}

{id:2,text:"Child1",xpath:"/Parent/Child1",parent:1,children:false}

{id:3,text:"Child2",xpath:"/Parent/Child2",parent:1,children:true}

{id:4,text:"Child3",xpath:"/Parent/Child3",parent:1,children:false}

{id:5,text:"Grandchild1",xpath:"/Parent/Child2/Grandchild1",parent:3,children:false}

{id:6,text:"Grandchild2",xpath:"/Parent/Child2/Grandchild2",parent:3,children:false}

{id:7,text:"Grandchild3",xpath:"/Parent/Child2/Grandchild3",parent:3,children:false}

Every document contains a node and has the following attributes

id -> Uniquer identifier

text -> node name

xpath -> path from root to node

parent -> node id of node's parent

children -> Boolean value representing whether the node has children

Once I provide a particular node id. I want all the descendants of the node. For example, if I provide node id as 1, I need results in the following pattern.

{
1:[{id:2,...},{id:3,...},{id:4,...}],
3:[{id:5,...},{id:6,...},{id:7,...}]
}

Is there any way to achieve this? Should I change the format in which data is stored to achieve this? Open to any suggestion. Thanks!

CodePudding user response:

I'm not sure how flexible you are with the output format, but here's one way to output all the descending generations of a given "id".

db.collection.aggregate([
  {"$match": {"id": 1}},
  {
    "$graphLookup": {
      "from": "collection",
      "startWith": "$id",
      "connectFromField": "id",
      "connectToField": "parent",
      "as": "descendents",
      "depthField": "generation"
    }
  },
  {"$unwind": "$descendents"},
  {"$sort": {"descendents.id": 1}},
  {
    "$group": {
      "_id": "$descendents.generation",
      "theChildren": {"$push": "$descendents"}
    }
  },
  {
    "$project": {
      "_id": 0,
      "theChildren": 1,
      "generation": {"$toInt": "$_id"},
      "parent": {"$first": "$theChildren.parent"}
    }
  }
])

Try it on mongoplayground.net.

  • Related