Search code examples
mongodbgomgo

Get all model tree child node in MongoDB with Go


I have data collection in MongoDB.

My data was built in model tree and relationship between child node and parent node is property parentid.

Here is my data architecture

enter image description here

And here is my sample data

{"_id":{"$oid":"5ebd05b52f3700008500220b"},"username":"DHBK","password":"123456","lastname":"DHBK","useremail":"[email protected]","usertel":"0907111001","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":null,"comid":"DHBK","comdepartment":"DHBK","usercode":"DHBK_0001","usertype":"ADMIN_COM"}
{"_id":{"$oid":"5ebd05b52f3700008500220c"},"username":"KHOA_DIEN","password":"123456","lastname":"KHOA_DIEN","useremail":"[email protected]","usertel":"0907111002","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"DHBK","comid":"DHBK","comdepartment":"KHOA_DIEN","usercode":"DHBK_0002","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f3700008500220d"},"username":"KHOA_XD","password":"123456","lastname":"KHOA_XD","useremail":"[email protected]","usertel":"0907111003","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"DHBK","comid":"DHBK","comdepartment":"KHOA_XD","usercode":"DHBK_0003","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f3700008500220e"},"username":"KHOA_CNTT","password":"123456","lastname":"KHOA_CNTT","useremail":"[email protected]","usertel":"0907111004","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"DHBK","comid":"DHBK","comdepartment":"KHOA_CNTT","usercode":"DHBK_0004","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f3700008500220f"},"username":"BOMON_TUDONG","password":"123456","lastname":"BOMON_TUDONG","useremail":"[email protected]","usertel":"0907111005","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"KHOA_DIEN","comid":"DHBK","comdepartment":"KHOA_DIEN","usercode":"DHBK_0005","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002210"},"username":"BOMON_VIENTHONG","password":"123456","lastname":"BOMON_VIENTHONG","useremail":"[email protected]","usertel":"0907111006","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"KHOA_DIEN","comid":"DHBK","comdepartment":"KHOA_DIEN","usercode":"DHBK_0006","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002211"},"username":"BOMON_HETHONG","password":"123456","lastname":"BOMON_HETHONG","useremail":"[email protected]","usertel":"0907111007","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"KHOA_DIEN","comid":"DHBK","comdepartment":"KHOA_DIEN","usercode":"DHBK_0007","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002212"},"username":"BOMON1_XD","password":"123456","lastname":"BOMON1_XD","useremail":"[email protected]","usertel":"0907111008","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"KHOA_XD","comid":"DHBK","comdepartment":"KHOA_XD","usercode":"DHBK_0008","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002213"},"username":"BOMON2_XD","password":"123456","lastname":"BOMON2_XD","useremail":"[email protected]","usertel":"0907111009","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"KHOA_XD","comid":"DHBK","comdepartment":"KHOA_XD","usercode":"DHBK_0009","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002214"},"username":"BOMON3_XD","password":"123456","lastname":"BOMON3_XD","useremail":"[email protected]","usertel":"0907111010","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"KHOA_XD","comid":"DHBK","comdepartment":"KHOA_XD","usercode":"DHBK_0010","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002215"},"username":"TRUONGKHOA_BMVT","password":"123456","lastname":"TRUONGKHOA_BMVT","useremail":"[email protected]","usertel":"0907111011","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"BOMON_VIENTHONG","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0011","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002216"},"username":"PHOKHOA_BMVT","password":"123456","lastname":"PHOKHOA_BMVT","useremail":"[email protected]","usertel":"0907111012","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"BOMON_VIENTHONG","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0012","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002217"},"username":"THUKY_BMVT","password":"123456","lastname":"THUKY_BMVT","useremail":"[email protected]","usertel":"0907111013","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"BOMON_VIENTHONG","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0013","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002218"},"username":"GV_BMVT","password":"123456","lastname":"GV_BMVT","useremail":"[email protected]","usertel":"0907111014","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"BOMON_VIENTHONG","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0014","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f37000085002219"},"username":"SV1_BMVT","password":"123456","lastname":"SV1_BMVT","useremail":"[email protected]","usertel":"0907111015","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"GV_BMVT","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0015","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f3700008500221a"},"username":"SV2_BMVT","password":"123456","lastname":"SV2_BMVT","useremail":"[email protected]","usertel":"0907111016","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"GV_BMVT","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0016","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f3700008500221b"},"username":"SV3_BMVT","password":"123456","lastname":"SV3_BMVT","useremail":"[email protected]","usertel":"0907111017","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"GV_BMVT","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0017","usertype":"USER_COM"}
{"_id":{"$oid":"5ebd05b52f3700008500221c"},"username":"SV4_BMVT","password":"123456","lastname":"SV4_BMVT","useremail":"[email protected]","usertel":"0907111018","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"GV_BMVT","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0018","usertype":"USER_COM"}
{"_id":{"$oid":"5ec642b2412b0000e70021a5"},"username":"KHOA_KT","password":"123456","lastname":"KHOA_KT","useremail":"[email protected]","usertel":"0907111002","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"DHKT","comid":"DHBK","comdepartment":"KHOA_KT","usercode":"DHKT_0002","usertype":"USER_COM"}
{"_id":{"$oid":"5ec642b2412b0000e70021a8"},"username":"BOMON_KTDOANHNGHIEP","password":"123456","lastname":"BOMON_KTDOANHNGHIEP","useremail":"[email protected]","usertel":"0907111005","userdate":"2020-05-05","userstatus":"ACTIVE","userparentid":"KHOA_KT","comid":"DHBK","comdepartment":"KHOA_KT","usercode":"DHKT_0005","usertype":"USER_COM"}
{"_id":{"$oid":"5ece3517b8d5570916d013f6"},"username":"SV5_BMVT","password":"123","lastname":"SV5_BMVT","useremail":"[email protected]","usertel":"0907111019","userdate":"2020-05-14","userstatus":"ACTIVE","userparentid":"GV_BMVT","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0019","usertype":"USER_COM"}
{"_id":{"$oid":"5eddf0a9b8d5570916dae6ff"},"username":"SV6_BMVT","password":"123456","lastname":"SV6_BMVT","useremail":"[email protected]","usertel":"0907111020","userdate":"2020-06-08","userstatus":"ACTIVE","userparentid":"GV_BMVT","comid":"DHBK","comdepartment":"BOMON_VIENTHONG","usercode":"DHBK_0019","usertype":"USER_COM"}

Now I want to get all child node of specific parent node. For example, I want to get all child node of DHBK node.

I have completed MongoDB shell to query this requirement.

Here is my MongoDB shell

var descendants=[]
var stack=[];
var item = db.users.findOne({username:"DHBK"});
stack.push(item);
while (stack.length>0){
    var currentnode = stack.pop();
    var children = db.users.find({userparentid:currentnode.username});
    while(true === children.hasNext()) {
        var child = children.next();
        descendants.push(child.username);
        stack.push(child);
    }
}
descendants.join(",")

It worked and showed me correct result. Here is my output result

KHOA_DIEN,KHOA_XD,KHOA_CNTT,BOMON1_XD,BOMON2_XD,BOMON3_XD,BOMON_TUDONG,BOMON_VIENTHONG,BOMON_HETHONG,TRUONGKHOA_BMVT,PHOKHOA_BMVT,THUKY_BMVT,GV_BMVT,SV1_BMVT,SV2_BMVT,SV3_BMVT,SV4_BMVT,SV5_BMVT,SV6_BMVT

Then I write Go code to implement this MongoDB shell.

Here is my code

 package main
 import (
     "context"
     "fmt"
     "strings"
     "time"
     "go.mongodb.org/mongo-driver/bson"
     "go.mongodb.org/mongo-driver/mongo"
     "go.mongodb.org/mongo-driver/mongo/options"
 )
 func main() {
      GetAllChildOfNode("DHBK")
 }
func GetAllChildOfNode(node string) error {
   ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
   client, err := mongo.Connect(ctx, options.Client().ApplyURI("URI string"))
   if err != nil {
       return err
   }
   defer client.Disconnect(ctx)
   database := client.Database("users")
   users := database.Collection("users")
   var descendants []string
   var stack []string
   err = users.FindOne(ctx, bson.M{"username": "DHBK"}).Decode(&stack)
   leng := len(stack)
   for leng > 0 {
       //I HaVE TROUBLE HERE
       currentnode := stack.
   }
   return nil
 }

But I have trouble implementing push, pop method and while loop as MongoDB shell by use Go.


Solution

  • Take a look if you are okay with $graphLookup limitations.

    If so, you can do it dbside in a single aggregation query:

    db.collection_name.aggregate([
      {$match: {username: "DHBK"}}, // select root document
      {
        $graphLookup: {             // load the tree as embedded docs
          from: "collection_name",
          startWith: "$username",
          connectFromField: "username",
          connectToField: "userparentid",
          as: "descendants",
        }
      },
      {$project: {                  // add root element if needed
          descendants: {$concatArrays: [["$$ROOT"], "$descendants"] }
      }},
      {$unwind: "$descendants"},    // final formatting steps
      {$replaceRoot: {newRoot: "$descendants"}},
      {$project: {descendants:0}}
    ])