# Query to recursively find the entire subgraph/cluster that a node belongs to

**URL:** <https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066>\
**Category:** Dgraph\
**Created:** [June 8, 2020, 9:47am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066 "2020-06-08T09:47:55Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![kevin.obrien](https://avatars.discourse-cdn.com/v4/letter/k/9f8e36/32.png) [@kevin.obrien](https://discuss.dgraph.io/u/kevin.obrien)\
**Post date:** [June 8, 2020, 9:47am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/1 "2020-06-08T09:47:55Z")

</div>

I have a graph of `customer_id`, `device_id`, `phone_number`, `email` nodes, where each `customer_id` node also has a `label` attribute. Each `customer_id` can have 0 or more `device_id`s, `phone_number`s, or `email`s with `has_device`, `has_phone_number`, `has_email` relationships.

I now want to query a single `customer_id` and return all other nodes in the graph that are connected in any way to this `customer_id`. In other words, I want to get the entire subgraph/cluster of nodes that a single `customer_id` is connected to.

Currently I am using the following query which works:

```auto
{
  cluster(func: eq(customer_id, 123456)) @recurse {
    customer_id
    label
    has_device
    ~has_device
    device_id
    has_phone_number
    ~has_phone_number
    phone_number
    has_email
    ~has_email
    email
	}
}

```

I am brand new to Dgraph and GraphQL, and so I am not sure if this query is the right way to do this, or if it is very inefficient, etc. Could you please recommend whether or not this query is ok for what I want, or are there better ways?

Schema:

 ![Screen Shot 2020-06-08 at 2.00.53 PM](https://canada1.discourse-cdn.com/flex007/uploads/dgraph/original/2X/4/4abcbb83fa5e3da43cd2698f3c3e327a953e3559.png)

---

<div class="post-metadata">

**Author:** ![Neeraj](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/neeraj/32/3104_2.png) [@Neeraj](https://discuss.dgraph.io/u/Neeraj)\
**Post date:** [June 8, 2020, 9:58am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/2 "2020-06-08T09:58:30Z")

</div>

Hey @kevin.obrien,  
Welcome to Dgraph. Can you please share the schema that you’re using?

---

<div class="post-metadata">

**Author:** ![kevin.obrien](https://avatars.discourse-cdn.com/v4/letter/k/9f8e36/32.png) [@kevin.obrien](https://discuss.dgraph.io/u/kevin.obrien)\
**Post date:** [June 8, 2020, 10:01am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/3 "2020-06-08T10:01:57Z")

</div>

Added it to my original question

---

<div class="post-metadata">

**Author:** ![Neeraj](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/neeraj/32/3104_2.png) [@Neeraj](https://discuss.dgraph.io/u/Neeraj)\
**Post date:** [June 8, 2020, 10:08am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/4 "2020-06-08T10:08:08Z")

</div>

Thank you @kevin.obrien.  
You don’t require to create separate nodes for email and phone\_number. You can just give them as predicates to the customer\_id or devide\_id nodes. Then you can search for `customer_id = 123456` and you can get all the devices connected to it and values of all of its predicates like `label, emails and phone_number etc`.

---

<div class="post-metadata">

**Author:** ![kevin.obrien](https://avatars.discourse-cdn.com/v4/letter/k/9f8e36/32.png) [@kevin.obrien](https://discuss.dgraph.io/u/kevin.obrien)\
**Post date:** [June 8, 2020, 10:11am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/5 "2020-06-08T10:11:13Z")

</div>

I don’t understand why `email`s and `phone_number`s would be treated differently to `device_id`s. They are all different types of nodes connected to `customer_id`s with `has_x` relationships. Could you write a sample query so I understand exactly what you mean please? Thanks

---

<div class="post-metadata">

**Author:** ![Anurag](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/anurag/32/2599_2.png) [@Anurag](https://discuss.dgraph.io/u/Anurag)\
**Post date:** [June 8, 2020, 10:15am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/6 "2020-06-08T10:15:02Z")

</div>

I think @kevin.obrien wants to do a graph search and needs all connected nodes and not just connected at level 1. The current query in the questions works since it runs the same query recursively on all the output nodes. But this can quickly time-out or not return anything if the sub-graph is very big. See [here.](https://dgraph.io/docs/query-language/#recurse-query)

@kevin.obrien from the query, I am trying to understand that do you want customers who share same phone number, email or device?

---

<div class="post-metadata">

**Author:** ![Neeraj](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/neeraj/32/3104_2.png) [@Neeraj](https://discuss.dgraph.io/u/Neeraj)\
**Post date:** [June 8, 2020, 10:16am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/7 "2020-06-08T10:16:30Z")

</div>

`device_id` is representing a device which is a different entity. Whereas `email` and `phone_number` are just values associated with the customer or the device.

---

<div class="post-metadata">

**Author:** ![Neeraj](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/neeraj/32/3104_2.png) [@Neeraj](https://discuss.dgraph.io/u/Neeraj)\
**Post date:** [June 8, 2020, 10:17am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/8 "2020-06-08T10:17:01Z")

</div>

But generally customers don’t share phone number or email.

---

<div class="post-metadata">

**Author:** ![kevin.obrien](https://avatars.discourse-cdn.com/v4/letter/k/9f8e36/32.png) [@kevin.obrien](https://discuss.dgraph.io/u/kevin.obrien)\
**Post date:** [June 8, 2020, 10:20am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/9 "2020-06-08T10:20:00Z")

</div>

@Anurag, yes I want all connected nodes, not just at level 1. In general terms, I want to return **all** nodes (customers, devices, phone numbers, email addresses) that have a path from the queried node to.

@Neeraj, actually in my case, there are customers sharing the same phone number or email addresses (fake, fraudulent accounts) and this is one of the problems we are trying to tackle.

---

<div class="post-metadata">

**Author:** ![Neeraj](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/neeraj/32/3104_2.png) [@Neeraj](https://discuss.dgraph.io/u/Neeraj)\
**Post date:** [June 8, 2020, 10:40am UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/10 "2020-06-08T10:40:06Z")

</div>

Oh, in that case, your query might be quite tricky. Let me tag @MichelDiz, he’ll be able to help you with the same.

---

<div class="post-metadata">

**Author:** ![Anurag](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/anurag/32/2599_2.png) [@Anurag](https://discuss.dgraph.io/u/Anurag)\
**Post date:** [June 8, 2020, 12:30pm UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/11 "2020-06-08T12:30:15Z")

</div>

Hi @kevin.obrien, Your query is correct and should work fine unless the graph explodes very quickly to very large number of nodes in which case you might want to restrict the depth by using `depth` paramater.

The below query identifies the two subgraphs based on whether `$name1` is `node g` or `node h`

```auto
query(func: eq(name, $name1) ) @recurse {
       name
       relation
       ~relation
   }

```

Schema

```auto
name: string @index(exact, trigram) .
relation: uid @reverse .

```

Mutation:

```auto
        _:nodeA <name> "node a" .
        _:nodeB <name> "node b" .
        _:nodeC <name> "node c" .
        _:nodeD <name> "node d" .
        _:nodeE <name> "node e" .
        _:nodeF <name> "node f" .
        _:nodeG <name> "node g" .
        _:nodeH <name> "node h" .
        _:nodeI <name> "node i" .
        _:nodeJ <name> "node j" .
        _:nodeK <name> "node k" .
        _:nodeA <relation> _:nodeG .
        _:nodeA <relation> _:nodeD .
        _:nodeB <relation> _:nodeA .
        _:nodeC <relation> _:nodeB .
        _:nodeH <relation> _:nodeI .
        _:nodeI <relation> _:nodeJ .
        _:nodeH <relation> _:nodeK .
        _:nodeK <relation> _:nodeJ .

```

---

<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:** [June 8, 2020, 6:03pm UTC](https://discuss.dgraph.io/t/query-to-recursively-find-the-entire-subgraph-cluster-that-a-node-belongs-to/7066/12 "2020-06-08T18:03:14Z")

</div>

Well, @kevin.obrien , the way you are doing it is the expected one for this scenario. Another way would be to write the same query in several blocks, but the data order could be wrong. Or you can do a single static query representing the whole tree you have.

A static query would be something like 1ms faster (that is, not worth it) in most cases. But it would certainly be much faster in gigantic Schemas. It is a trade-off.

### TIP:

To make your query smaller, you can use the Type Trick. Taking @Anurag’s sample. You can do this

```auto
{
  query(func: eq(name_2, "node g") ) @recurse {
       expand(a_b_c_and_d,e_f_g_and_h,rest)
       #expand( myType1, myType2, myType3 )
   }
}

```

This will use the type to expand all edges you have.

### Modified sample:

> Some repeated preds are just examples

```auto
name: string @index(exact, trigram) .
name_2: string @index(exact, trigram) .
name_3: string @index(exact, trigram) .
relation: [uid] @reverse .

type a_b_c_and_d {
 name
 relation
 <~relation>
}

type e_f_g_and_h {
 name_2
 relation
 <~relation>
}

type rest {
 name_3
 relation
 <~relation>
}

```

```auto
{
    set {
      _:nodeA <name> "node a" .
      _:nodeA <dgraph.type> "a_b_c_and_d" .

      _:nodeB <name> "node b" .
      _:nodeB <dgraph.type> "a_b_c_and_d" .

      _:nodeC <name> "node c" .
      _:nodeC <dgraph.type> "a_b_c_and_d" .

      _:nodeD <name> "node d" .
      _:nodeD <dgraph.type> "a_b_c_and_d" .

      _:nodeE <name_2> "node e" .
      _:nodeE <dgraph.type> "e_f_g_and_h" .

      _:nodeF <name_2> "node f" .
      _:nodeF <dgraph.type> "e_f_g_and_h" .

      _:nodeG <name_2> "node g" .
      _:nodeG <dgraph.type> "e_f_g_and_h" .

      _:nodeH <name_2> "node h" .
      _:nodeH <dgraph.type> "e_f_g_and_h" .

      _:nodeI <name_3> "node i" .
      _:nodeI <dgraph.type> "rest" .

      _:nodeJ <name_3> "node j" .
      _:nodeJ <dgraph.type> "rest" .

      _:nodeK <name_3> "node k" .
      _:nodeK <dgraph.type> "rest" .

      _:nodeA <relation> _:nodeG .
      _:nodeA <relation> _:nodeD .
      _:nodeB <relation> _:nodeA .
      _:nodeC <relation> _:nodeB .
      _:nodeH <relation> _:nodeI . 
      _:nodeI <relation> _:nodeJ .
      _:nodeH <relation> _:nodeK .
      _:nodeK <relation> _:nodeJ .
    }
}

```
