Get the Hirearchy View In MongoDB and Spring Boot

   Here, I've a sample document of my DB Collection,
    {     
           user:"758bd45b-0741-430b-ae3c-af0f1c2e42b7"     
           referral:"467da3eb-3229-4bb2-82c0-3b2f440d378c"     
           refUserId:"84e8c706-8d26-43e9-9d9a-1df114a3e97d"     
           status:"SUCCESS" 
      }

Here, User id UserId, refUserIs means the referee Who invited this user. What I expecting is I need to get the tree/ Hirearch view with these details.

Example Scenario:
If I enter a UserID then It has to show me the details in tree view like the below expecting result
{
“id”: 2,
“full_name”: “Henry”,
“parent”: {
“id”: 1,
“full_name”: “William”
},
“children”: [
{
“id”: 3,
“full_name”: “Matt”,
“parent”: {
“id”: 2,
“full_name”: “Henry”,
“parent”: {
“id”: 1,
“full_name”: “William”
}
}
},
{
“id”: 4,
“full_name”: “Alisa”,
“parent”: {
“id”: 2,
“full_name”: “Henry”,
“parent”: {
“id”: 1,
“full_name”: “William”
}
}
}
]
}

It’s for just one user, similarly have to get them all collection under one endpoint with the hierarchy view and get the depth of each userflow.

I will be grateful if you can suggest me the correct MongoDB Queries and SpringBoot Example(If Possible)

Hi @Abishan_Parameswaran,

I think what you are trying to do is a $graphLookup query.

You can find an example in the documentation here.

Cheers,
Maxime.

Hi @MaBeuLux88 I tried it earlier but didn’t get as I expected

Humm it shouldn’t be too far I guess.
Can you please provide some input documents & the expected output based on these documents?
Please use markdown syntax to insert code blocks so it’s easier to read & understand.
Can you please also provide the query / commands you have tried so far based on these documents? This would help as well.

Thanks.

  {     
       user:"002",     
       refUserId:"001",     
       status:"SUCCESS" 
  },

  {     
       user:"003",     
       refUserId:"001",     
       status:"SUCCESS" 
  }

I’ve inputs/documents like this in my collection. I’m expecting the output like below

     {

          parent:001,

          child:

            {

              id:002

              status:SUCCESS

            },

            {

              id:003

              status:SUCCESS

            }

      }

If I enter userId it should return me the child and parent. Including the Depth(How many children)

This is the Query that I’ve used:
GraphLookupOperation graphLookupOperation = graphLookup(“user_referral”).startWith(“refUserId”).connectFrom("$user").connectTo(
“user”).maxDepth(3).as(“treeStructure”);

NOTE: All the documents are in the same collection(Only Collection)

Hi @MaBeuLux88 this is how I expect

It works for me. But you are missing the parent doc in your example.

Input docs:

db.coll.insertMany(
[
  {
    _id: ObjectId("612f84891f2da394c2b8ed21"),
    user: '002',
    refUserId: '001',
    status: 'SUCCESS'
  },
  {
    _id: ObjectId("612f84891f2da394c2b8ed22"),
    user: '003',
    refUserId: '001',
    status: 'SUCCESS'
  },
  {
    _id: ObjectId("612f85a11f2da394c2b8ed23"),
    user: '001',
    status: 'SUCCESS'
  }
])

Query:

db.coll.aggregate(
[
  {
    "$graphLookup": {
      "from": "coll",
      "startWith": "$user",
      "connectFromField": "user",
      "connectToField": "refUserId",
      "as": "children",
      "maxDepth": 3
    }
  }
])

Result:

[
  {
    _id: ObjectId("612f84891f2da394c2b8ed21"),
    user: '002',
    refUserId: '001',
    status: 'SUCCESS',
    children: []
  },
  {
    _id: ObjectId("612f84891f2da394c2b8ed22"),
    user: '003',
    refUserId: '001',
    status: 'SUCCESS',
    children: []
  },
  {
    _id: ObjectId("612f85a11f2da394c2b8ed23"),
    user: '001',
    status: 'SUCCESS',
    children: [
      {
        _id: ObjectId("612f84891f2da394c2b8ed22"),
        user: '003',
        refUserId: '001',
        status: 'SUCCESS'
      },
      {
        _id: ObjectId("612f84891f2da394c2b8ed21"),
        user: '002',
        refUserId: '001',
        status: 'SUCCESS'
      }
    ]
  }
]

Cheers,
Maxime.

Hi @MaBeuLux88 I’m checking that again if you don’t mind can you share the aggregation that you have done in the compass? That will be easy for me to check with my collection my original doc slightly different from the one I’ve mentioned in the Problem

The query I’m using is here, in my previous post.

You can insert it in Compass using the New Pipeline From Text option.

image

Cheers,
Maxime.

Hi @MaBeuLux88 ,

It worked for me as I expected with your immense support. I’ve another requirement under this scenario I’m putting this here hope I can get a good solution from you.

{
    _id: ObjectId("612f84891f2da394c2b8ed21"),
    user: '002',
    refUserId: '001',
    status: 'SUCCESS'
  },
  {
    _id: ObjectId("612f84891f2da394c2b8ed22"),
    user: '003',
    refUserId: '001',
    status: 'SUCCESS'
  },
  {
    _id: ObjectId("612f85a11f2da394c2b8ed23"),
    user: '001',
    status: 'SUCCESS'
  }

This is the previous data set. But when I’m changing it bit like below

{
    _id: ObjectId("612f84891f2da394c2b8ed21"),
    user: '002',
    refUserId: '001',
    status: 'SUCCESS'
  },
  {
    _id: ObjectId("612f84891f2da394c2b8ed22"),
    user: '003',
    refUserId: '002',
    status: 'SUCCESS'
  },
  {
    _id: ObjectId("612f85a11f2da394c2b8ed23"),
    user: '001',
    status: 'SUCCESS'
  }

I’m getting an output like this

001

Here you can Identify this it’s returning the same Objects even after I change the values. Actually it has to be like a below sample example(this is what I expect)

{
  "_id": {
    "$oid": "612f8bccc8188663637695cf"
  },
  "user": "001",
  "status": "SUCCESS"
  "child" : Array
     {
       "_id": {
       "$oid": "612f8bccc8188663637695cd"
       },
      "user": "002",
      "refUserId": "001",
      "status": "SUCCESS"
      "child" : Array
           {
          "_id": {
          "$oid": "612f8bccc8188663637695cd"
          },
          "user": "003",
          "refUserId": "002",
          "status": "SUCCESS"
         }
}

I’ll be grateful if you can help me to solve this problem

It’s giving you the full “hierarchy” - you can add the optional field depthField to get back how deep from top level the referee is.

What Asya means is this:

> db.coll.insertMany([{ _id: ObjectId("612f84891f2da394c2b8ed21"), user: '002', refUserId: '001', status: 'SUCCESS' }, { _id: ObjectId("612f84891f2da394c2b8ed22"), user: '003', refUserId: '002', status: 'SUCCESS' }, { _id: ObjectId("612f85a11f2da394c2b8ed23"), user: '001', status: 'SUCCESS' }])

Note the extra "depthField": "depth" in my pipeline.

> db.coll.aggregate( [ { "$graphLookup": { "from": "coll", "startWith": "$user", "connectFromField": "user", "connectToField": "refUserId", "as": "children", "maxDepth": 3, "depthField": "depth" } }])
[
  {
    _id: ObjectId("612f84891f2da394c2b8ed21"),
    user: '002',
    refUserId: '001',
    status: 'SUCCESS',
    children: [
      {
        _id: ObjectId("612f84891f2da394c2b8ed22"),
        user: '003',
        refUserId: '002',
        status: 'SUCCESS',
        depth: Long("0")
      }
    ]
  },
  {
    _id: ObjectId("612f84891f2da394c2b8ed22"),
    user: '003',
    refUserId: '002',
    status: 'SUCCESS',
    children: []
  },
  {
    _id: ObjectId("612f85a11f2da394c2b8ed23"),
    user: '001',
    status: 'SUCCESS',
    children: [
      {
        _id: ObjectId("612f84891f2da394c2b8ed21"),
        user: '002',
        refUserId: '001',
        status: 'SUCCESS',
        depth: Long("0")
      },
      {
        _id: ObjectId("612f84891f2da394c2b8ed22"),
        user: '003',
        refUserId: '002',
        status: 'SUCCESS',
        depth: Long("1")
      }
    ]
  }
]

As you can see in the output, there is a new field depth which tells you how deep you had to go to find this child… But that doesn’t gives you the “tree-like” output that you were hoping for.

So I’m not sure if it’s answering your question or not @Abishan_Parameswaran but I have no idea how to get the output you want without a more complexe aggregation pipeline that isn’t trivial, at least for me…

Cheers,
Max.