# Recursive query with dgraph

**URL:** <https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148>\
**Category:** Dgraph\
**Created:** [March 6, 2019, 9:54pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148 "2019-03-06T21:54:05Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 6, 2019, 9:54pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/1 "2019-03-06T21:54:05Z")

</div>

Hi,  
I am trying to fetch all the children of a given node. I read through the documentation and it seems like  
`recurse` would be something that I want to use but after much hit and trial I am not able to figure it out.  
In particular, I want to get all child nodes (via isSubsidiary edge) of a node such that enitity\_id=“1”.  
I have the entity\_id and isSubsidiary (with reverse edge) predicates in my dgraph instance as follows:

1\<-2\<-3\<-4  
^  
|  
5  
^  
|  
6  
(Please, don’t mind my ascii art skills.)  
And I am expecting my result set to contain the entity\_ids [1,2,3,4,5,6] as they all belong to the same tree (1’s children’s tree). Any help would be greatly appreciated.

---

<div class="post-metadata">

**Author:** ![dmai](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/dmai/32/1254_2.png) [@dmai](https://discuss.dgraph.io/u/dmai)\
**Post date:** [March 6, 2019, 9:58pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/2 "2019-03-06T21:58:15Z")

</div>

Can you share the query you tried? A `@recurse` query should work for you.

---

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 6, 2019, 11:07pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/3 "2019-03-06T23:07:30Z")

</div>

Consider the entity with entity\_id=“0FPWZZ-E” as follows:

```auto
{
  all_subsidiaries(func:eq(entity_id, "0FPWZZ-E")) {
	~isSubsidiaryOfFilermstPriorityNoOverlap {
               entity_id
          }
  }
}

```

The above query gives me the following response:

```json
{
  "data": {
    "all_subsidiaries": [
      {
        "~isSubsidiaryOfFilermstPriorityNoOverlap": [
          {
            "entity_id": "0HCV3V-E"
          },
          {
            "entity_id": "0FQGTM-E"
          },
          {
            "entity_id": "0C755F-E"
          },
          {
            "entity_id": "0J6KQ0-E"
          },
          {
            "entity_id": "0H0H9K-E"
          },
          {
            "entity_id": "0FQD05-E"
          },
          {
            "entity_id": "003JLG-E"
          },
          {
            "entity_id": "0HHDMB-E"
          },
          {
            "entity_id": "0HG6GW-E"
          },
          {
            "entity_id": "0H3DZ4-E"
          },
          {
            "entity_id": "0J0SDQ-E"
          },
          {
            "entity_id": "0JG29M-E"
          },
          {
            "entity_id": "0DLJSM-E"
          },
          {
            "entity_id": "0FSW5G-E"
          },
          {
            "entity_id": "0HYRRF-E"
          },
          {
            "entity_id": "0DLC27-E"
          }
        ]
      }
    ]
   }
}

```

Now I try the following query and don’t get any data.

```auto
{
  all_subsidiaries(func: eq(entity_id, "0FPWZZ-E")) @recurse(depth:5, loop:false) {
	~isSubsidiaryOfFilermstPriorityNoOverlap {
            entity_id
        }
 }
}

```

Clearly, the data is there but my `recurse` query is wrong. Any ideas?

---

<div class="post-metadata">

**Author:** ![dmai](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/dmai/32/1254_2.png) [@dmai](https://discuss.dgraph.io/u/dmai)\
**Post date:** [March 6, 2019, 11:24pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/4 "2019-03-06T23:24:00Z")

</div>

[https://docs.dgraph.io/query-language/#recurse-query](https://docs.dgraph.io/query-language/#recurse-query)

The `@recurse` query docs say you can only specify one-level of predicates. At every node hop the query will traverse through all the listed predicates.

A single-level of predicates means the query should be shaped like this:

```auto
{
  all_subsidiaries(func: eq(entity_id, "0FPWZZ-E")) @recurse(depth:5, loop:false) {
    ~isSubsidiaryOfFilermstPriorityNoOverlap
    entity_id
  }
}

```

---

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 6, 2019, 11:35pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/5 "2019-03-06T23:35:09Z")

</div>

@dmai That worked. Thanks a lot !

---

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 7, 2019, 4:08pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/6 "2019-03-07T16:08:50Z")

</div>

@dmai I have one more question regarding `recurse` query. I am trying to write a query to get to  
the ultimate parent node from a child as follows:

```auto
{
  ultimate_parent(func: eq(entity_id, "05QXVL-E")) @recurse(loop:false) {
    isSubsidiaryOfFilermstPriorityNoOverlap
    entity_id
  }
}

```

The above query returns the path from “05QXVL-E” to “0FPWZZ-E”. But I only need “0FPWZZ-E”  
in the result set and not the whole path. Is there a way to do that? Thanks for your help so far.

---

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 8, 2019, 6:26pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/7 "2019-03-08T18:26:07Z")

</div>

@MichelDiz Would you be able to help me with the query above?

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [March 8, 2019, 6:57pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/8 "2019-03-08T18:57:59Z")

</div>

Not sure, but could be:

```auto
{
  var(func: eq(entity_id, "05QXVL-E")) @recurse(loop:false) {
    GetIT as uid
    isSubsidiaryOfFilermstPriorityNoOverlap
    entity_id
  }
  
  ultimate_parent(func: uid(GetIT)) @filter(Not eq(entity_id, "05QXVL-E")){
    uid
    expand(_all_)
  }
}

```

If not so, send us results output desired ones and actual ones.

---

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 8, 2019, 7:26pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/9 "2019-03-08T19:26:48Z")

</div>

@MichelDiz Thanks for the quick response. It seems the query you posted above prints all nodes of the path except the starting one. But what I need is just the ultimate parent. That is, “0FPWZZ-E”. In particular, consider the following snippet:

```auto
{
  path_to_ultimate_parent(func: eq(entity_id, "05QXVL-E")) @recurse(loop:false) {
    isSubsidiaryOfFilermstPriorityNoOverlap
    entity_id
  }
}

```

It gives me the following result:

```json
    "path_to_ultimate_parent": [
      {
        "isSubsidiaryOfFilermstPriorityNoOverlap": [
          {
            "isSubsidiaryOfFilermstPriorityNoOverlap": [
              {
                "isSubsidiaryOfFilermstPriorityNoOverlap": [
                  {
                    "isSubsidiaryOfFilermstPriorityNoOverlap": [
                      {
                        "entity_id": "0FPWZZ-E"
                      }
                    ],
                    "entity_id": "003JLG-E"
                  }
                ]
              }
            ],
            "entity_id": "0029WX-E"
          }
        ],
        "entity_id": "05QXVL-E"
      }
    ]

```

Which is the path from child to its ultimate parent. What I need is the following:

```json
"ultimate_parent" : [
  {
    "entity_id" : “0FPWZZ-E”
  }
]

```

Please let me know if you have anymore questions.

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [March 8, 2019, 8:10pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/10 "2019-03-08T20:10:31Z")

</div>

Sorry, that isn’t possible.

Wha you can do is or loop through the arrays levels in your client side. Or do something like this below and loop for the last value from the list. But isn’t guarantee that the sorting order will be always the same. Although normalize directive usually will do the same order from the previous format of the recurse query.

```auto
{
   path_to_ultimate_parent(func: eq(entity_id, "05QXVL-E")) @recurse @normalize {
		 expand(_all_) { expand(_all_)}
  }
}

```

> PS. Normalize only works using “`expand(_all_)`”. And aliases.

### Result

```auto
{
  "data": {
    "path_to_ultimate_parent": [
      {
        "entity_id": [
          "05QXVL-E",
          "0029WX-E",
          "003JLG-E",
          "0FPWZZ-E"
        ],
        "uid": "0xf9063"
      }
    ]
  }
}

```

> PS. That’s the only way in my view. The other ways can’t indeed guarantee that the sorting order will be always the same.

---

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 8, 2019, 8:43pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/11 "2019-03-08T20:43:11Z")

</div>

@MichelDiz, I think I have a query that does find out the ultimate parent.

```auto
{
   uid_for_ultimate_parent (func: eq(entity_id, "05QXVL-E")) @recurse @normalize {
     isSubsidiaryOfFilermstPriorityNoOverlap
     uid : entity_id
  }
}

```

Gives me the following result:

```json
{
    "uid_for_ultimate_parent": [
      {
        "uid": "0FPWZZ-E"
      }
    ]
}

```

I have tried with a few other children and it seems to work. I have no clue why though. Any ideas?

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [March 8, 2019, 9:55pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/12 "2019-03-08T21:55:33Z")

</div>

This is weird. Sounds like a nice bug feature tho. Nice finding!

It seems to me that when using the alias ​​for UID, you have in some way forced the value of entity\_id to be inserted into this. The rule is that UID must be unique per block, maybe this has bumped into this premise. You have recategorized entity\_id to be uid. In all blocks it have been renamed to UID. And when it came time to use `@normalize` Dgraph overwritten all values ​​as ‘uid’ block by block until get the final nested block.

That’s just a theory. If you do `uid : uid ` you gonna have the same result but will come only (the desired one) the UID from the last nested block. That’s nice!

Try this query:

```auto
{
   uid_for_ultimate_parent (func: eq(entity_id, "05QXVL-E")) @recurse @normalize
  {
     isSubsidiaryOfFilermstPriorityNoOverlap
     FG as uid : uid
  }
  
  finalQ(func: uid(FG)) {
    uid
    entity_id
  }
  
}

```

If this was indeed something valid in the Dgraph. The second query would only come with a single node.

```auto
{
  "data": {
    "uid_for_ultimate_parent": [
      {
        "uid": "0xf9063"
      }
    ],
    "finalQ": [
      {
        "uid": "0xf9061"
      },
      {
        "uid": "0xf9062",
        "entity_id": "003JLG-E"
      },
      {
        "uid": "0xf9063",
        "entity_id": "0FPWZZ-E"
      },
      {
        "uid": "0xf9064",
        "entity_id": "05QXVL-E"
      },
      {
        "uid": "0xf9065",
        "entity_id": "0029WX-E"
      }
    ]
  }
}

```

---

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 11, 2019, 6:46pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/13 "2019-03-11T18:46:33Z")

</div>

@MichelDiz I executed the following query:

```auto
{
  ultimate_parent_uids(func: eq(entity_id, "0847GF-E")) @recurse @normalize {
     isSubsidiaryOfFilermstPriorityNoOverlap
     parent_uid as uid : uid 
  }
  ultimate_parents(func:uid(parent_uid)) {
    uid
    entity_id
  }
}

```

And got the following result:

```json
{
   "ultimate_parent_uid": [
      {
        "uid": "0x1b32457"
      }
    ],
    "ultimate_parents": [
      {
        "uid": "0x1b32457",
        "entity_id": "05L5R1-E"
      },
      {
        "uid": "0x23a18bd",
        "entity_id": "0847GF-E"
      }
    ]
}

```

I assume you are not surprised with the second result, but I surely am. Is there any workaround via which  
I can operate on the ultimate\_parent uids instead of flattened path in the second block?  
If not, then it will require my app to do this in two steps (query ultimate parents and then filter them on some predicate in the second dgraph request) which does not seem ideal. Do you think it can be an acceptable feature request?  
Thanks for your help so far.

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [March 11, 2019, 8:08pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/14 "2019-03-11T20:08:23Z")

</div>

> [@hbarthwal](#):
>
> I assume you are not surprised with the second result, but I surely am. Is there any workaround via which

I’m not cuz the variable tend to maps only UIDs and you can’t pass a value from `@normalize` as UID map. So from parent\_uid would always come a map of UID’s, not values. Unless you wanted a value (but it did not work for uid(X) func).

I think that give `@recurse` directive a new feature would be good. For the “ultimate parent” giving the last (or multiple last) node of a recurse search. Would be nice to do it without tricks. But not sure how it would be useful for others. Knowing this would be important to allocate a Dev Core for this. Today they are almost 99% working on critical things for next release, features are in last place of importance now. Unless it’s easy to implement and people need it.

#### One more thing

I think depending on your context it would be worth doing a “tag” to find out who the “ultimate\_parent” is.

The idea would be to mark the “ultimate\_parent” with a Boolean predicate. That way we can ensure that only it will return from a recursive query. It could even be a Facet.

e,g:

```auto

{
       "entity_id": "0FPWZZ-E",
       "ultimate": "true"
}

```

And

```auto
{
  ultimate_parent(func: eq(entity_id, "05QXVL-E")) @recurse(loop:false) {
    GetIT as uid
    isSubsidiaryOfFilermstPriorityNoOverlap @filter(eq(ultimate, "true"))
    entity_id
  }

  ultimate_parent(func: uid(GetIT)) @filter(Not eq(entity_id, "05QXVL-E")){
    uid
    expand(_all_)
  }
}

```

---

<div class="post-metadata">

**Author:** ![hbarthwal](https://avatars.discourse-cdn.com/v4/letter/h/46a35a/32.png) [@hbarthwal](https://discuss.dgraph.io/u/hbarthwal)\
**Post date:** [March 11, 2019, 8:31pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/15 "2019-03-11T20:31:28Z")

</div>

> > Today they are almost 99% working on critical things for next release…

Makes sense.

> > The idea would be to mark the “ultimate\_parent” with a Boolean predicate…

I am guessing what you are suggesting here is to generate mutations based on the ultimate\_parent uids query’s result set that marks them is\_ultimate\_parent. And then the queries you suggested below can use that new predicate to filter out the nodes. Correct?

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [March 11, 2019, 9:38pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/16 "2019-03-11T21:38:23Z")

</div>

> [@hbarthwal](#):
>
> Correct?

More or less that.

You could create a query that checks whether a node is the last of the chain or not. Maybe a bot or a background task hunting for nodes with this characteristics. If the Node has no children, only parent it is indeed the ultimate at that moment. So you mutate it as `"ultimate": "true"`.

You could use [upsert procedure](https://docs.dgraph.io/howto/#upsert-procedure) and soon we will have the new transaction `#3059`. With the new txn this operation would be simpler.

> <https://github.com/dgraph-io/dgraph/issues/3059>
>
> This operation would allow a user to run a query, and use its results (via varia…bles) to execute the mutation. This would then allow upserts to happen, without doing multiple network calls to the DB.
> 
> \`\`\`
> txn {
> query {
> me(func: eq(email, "someone@gmail.com")) {
> v as uid
> }
> }
> 
> mutation @if(eq(len(v), 0)) {
> set {
> \<uid(v)\> \<name\> "Some One" .
> \<uid(v)\> \<email\> "someone@gmail.com" .
> }
> }
> }
> \`\`\`
> 
> This txn would check for an account with \`email=someone@gmail.com\`, and only if it is present, would
> it run the mutation.
> 
> This should return the result of query, normally. And also return the result of the mutation.
> 
> Additionally, we should be able to optionally do the mutation, iff the email is already present.
> \`\`\`
> txn {
> query {
> me(func: eq(email, "someone@gmail.com")) {
> v as uid
> }
> }
> 
> mutation @if(gt(len(v), 0)) {
> set {
> \<uid(v)\> \<name\> "Changed Name" .
> }
> }
> }
> \`\`\`
> This would introduce a new txn operator, and a new if directive applicable for mutations.

---

<div class="post-metadata">

**Author:** ![rstreeting](https://avatars.discourse-cdn.com/v4/letter/r/898d66/32.png) [@rstreeting](https://discuss.dgraph.io/u/rstreeting)\
**Post date:** [November 20, 2020, 4:39pm UTC](https://discuss.dgraph.io/t/recursive-query-with-dgraph/4148/17 "2020-11-20T16:39:16Z")

</div>

I know this is an old post now, but I figured I’d post my solution for any future viewers.

To get _just_ the ultimate parent, you can store the flat list of uids in a variable, and then filter the results in a second query to only those that _don’t_ have the edge you are recursing on. For Himanshu’s query above:

```auto
{
  var(func: eq(entity_id, "05QXVL-E")) @recurse(loop:false) {
    isSubsidiaryOfFilermstPriorityNoOverlap
    x as entity_id
  }

  ultimate_parent(func: uid(x)) @filter(not has(isSubsidiaryOfFilermstPriorityNoOverlap)) {
    entity_id: val(x)
  }
}

```
