# Comparing two predicate counts in a filter

**URL:** <https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955>\
**Category:** Dgraph\
**Tags:** kind:question\
**Created:** [February 9, 2020, 5:11pm UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955 "2020-02-09T17:11:04Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![kesor](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/kesor/32/2495_2.png) [@kesor](https://discuss.dgraph.io/u/kesor)\
**Post date:** [February 9, 2020, 5:11pm UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/1 "2020-02-09T17:11:04Z")

</div>

Trying to find all nodes that have the same number of uids in `SecondList` as they have in `FirstList`.

```auto
query {
  nodes(func:type("Node"))
    @filter(eq(count(FirstList), count(SecondList))
    @cascade
  {
    # FirstList {
    # uid
    # }
    # SecondList {
    # uid
    # }
  }
}

```

But there is an error from dgraph saying “`Multiple functions as arguments not allowed`”.

Is there some other way that this can be achieved?

---

<div class="post-metadata">

**Author:** ![ppp225](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/ppp225/32/2007_2.png) [@ppp225](https://discuss.dgraph.io/u/ppp225)\
**Post date:** [February 9, 2020, 5:15pm UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/2 "2020-02-09T17:15:07Z")

</div>

Have you tried using variables to store the count result, and using it in the filter?

---

<div class="post-metadata">

**Author:** ![kesor](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/kesor/32/2495_2.png) [@kesor](https://discuss.dgraph.io/u/kesor)\
**Post date:** [February 9, 2020, 5:48pm UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/3 "2020-02-09T17:48:36Z")

</div>

Sure, but it has the same problem since the `eq` function has two `val()` functions inside…

```auto
query {
  ID as var(func:type("Node")) {
    firstCount as count(Links @filter(type("Node")))
    secondCount as count(Links @filter(ge(count(Links),1)))
  }
  nodes(func:uid(ID))
      @filter(eq(val(firstCount), val(secondCount)))
  {
    uid
  }
}

```

Same error: `Multiple functions as arguments not allowed`.

---

<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:** [February 9, 2020, 9:40pm UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/4 "2020-02-09T21:40:03Z")

</div>

None of those syntaxes doesn’t exists in `Graphql+-` as you can see in the docs [https://docs.dgraph.io/query-language/#inequality](https://docs.dgraph.io/query-language/#inequality)

Try something like this

```auto
{
  var(func:type("Node")) {
   F as FirstList
   S as SecondList
  }
  
  q(func: uid(F)) @filter(uid(S)) {
    uid
    expand(_all_)
  }
}

```

What gonna happen is, the query block will expand all nodes in FirstList, and then filter to show only those nodes that exists in both edges.

Assuming that:

```auto
FirstList has:
0x20
0x21
0x23
0x24
0x25
0x26

SecondList has:
0x21
0x23
0x25
0x26

```

The result for the query should be:

```auto
0x21
0x23
0x25
0x26

```

You can also use `q(func: uid(F)) @filter(NOT uid(S))`  
The result for the query should be:

```auto
0x20
0x24

```

---

<div class="post-metadata">

**Author:** ![kesor](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/kesor/32/2495_2.png) [@kesor](https://discuss.dgraph.io/u/kesor)\
**Post date:** [February 10, 2020, 10:06am UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/5 "2020-02-10T10:06:22Z")

</div>

This is not quite the same thing as I asked. I don’t care about the actual nodes, I only care about the **amount** of nodes.

All I care is to find UIDs whose list _lengths_ are the same, without caring about the content of these lists.

For example, given a genealogy tree find all people who have the same number of siblings as their number of children. Naturally their brothers and sisters are not the same people as their children. And the query would find people who have 4 siblings and 4 children, as well as those who only have 1 sibling and 1 child. But not those who have 3 siblings and 2 children, or 5 children but 1 sibling.

---

<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:** [February 12, 2020, 4:37am UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/6 "2020-02-12T04:37:49Z")

</div>

Hum, I was trying to accomplish what I understood from your queries. What the syntaxes would mean. But as you explained it better, I can see that the queries are far from it. And I can say that is not possible to do it in a practical way. Bellow follows a kind of “hack” way to do comparisons and getting a meaningful result from it (Like “true/false”).

It is “hacky”, which means it can’t have the desired result in other scenarios and it abuses from the query system.

> I’ve used the other sample of yours to do this example.

```auto
{
  var(func: uid(0x7)) {
    A as count(Links) #It has 2 links
  }
  var(func: uid(0x6)) {
    B as count(Links) #It has 1 link
  }

  var() {
    G as sum(val(A))
    T as sum(val(B))
  }
  me() {
    result: math( G > T )
  }
}

```

## Result

```auto
{
  "data": {
    "me": [
      {
        "result": true
      }
    ]
  }
}

```

> [@kesor](#):
>
> For example, given a genealogy tree find all people who have the same number of siblings as their number of children. Naturally their brothers and sisters are not the same people as their children. And the query would find people who have 4 siblings and 4 children, as well as those who only have 1 sibling and 1 child. But not those who have 3 siblings and 2 children, or 5 children but 1 sibling.

And this needs a deeper look and thought to answer.

---

<div class="post-metadata">

**Author:** ![amaster507](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/amaster507/32/4123_2.png) [@amaster507](https://discuss.dgraph.io/u/amaster507)\
**Post date:** [August 21, 2020, 1:20am UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/7 "2020-08-21T01:20:37Z")

</div>

For curiosity and to better understand the fundamentals, why does dgraph not support two functions:

> [@kesor](#):
>
> `@filter(eq(val(firstCount), val(secondCount)))`

What is preventing dgraph from being able to process this? If it can evaluate a function on one side, shouldn’t it also be able to evaluate a function on the other side of an equation? Maybe this is a little deeper subject than the OP, sorry.

---

<div class="post-metadata">

**Author:** ![Jaime](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/jaime/32/9618_2.png) [@Jaime](https://discuss.dgraph.io/u/Jaime)\
**Post date:** [January 26, 2023, 6:11pm UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/8 "2023-01-26T18:11:18Z")

</div>

A couple of years passed and I am interested in this feature. As amaster says this would be a normal aproach:

```auto
@filter(eq(val(firstCount), val(secondCount)))

```

but this does not work, and I have to do something like:

```auto
var() { 
    equal as math(firstCount- secondCount)
}
query(func:...) @filter(eq(val(equal),0)) {
    uid
}

```

Things like this make DQL feel superhacky sometimes ☹

In my use case I want to fetch n nodes of type A related to nodes of type B and get only the nodes of type b that are related to each of the n type A nodes, to do that I already use the variable propagation thing that also feel extremely counter intuitive but works like a charm:

```auto
  var(func: type(A)) @filter(eq(name,"foo")) { #can be 1,2 or n
      A as uid
      Acount as count(uid)
      paths as math(1)
      a as A.linktoB {
        ticks as math(paths) #the variable propagation math trick
      }
  }

 var() { 
     equal as math(ticks - Acount)
 } #if acount == ticks means that the nodeB is related to all the nodesA
  
 validB as var(func: uid(a),first:10) @filter(eq(val(equal),0)) { uid }  
  
 output(func: uid(A)) {
     A.name
     A.linktoB @filter(uid(validB)) {
	   B.name
     }
 }

```

It works, but the amaster aproach would make this more readable and easier for everybody.  
What do you think?

---

<div class="post-metadata">

**Author:** ![Raphael](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/raphael/32/10075_2.png) [@Raphael](https://discuss.dgraph.io/u/Raphael)\
**Post date:** [January 30, 2023, 12:54am UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/9 "2023-01-30T00:54:20Z")

</div>

I think it’s a fair request. Let me add it to our backlog. As the two variables are both UID maps we should be able to evaluate this filter condition easily.

> <https://github.com/dgraph-io/dgraph/issues/8636>
>
> \### Use case and current behavior
> 
> It is useful to compare variables computed on… selected nodes.
> For example :
> Type A as relationships to B and C. Find the node A which have the same number of relationships to B and to C.
> 
> 
> \### Enhancement
> 
> @filter(eq(val(firstCount), val(secondCount))) should be supported.
> 
> 
> \### Solution proposal
> 
> \_No response\_
> 
> \### Links to Discuss, RFC or previous Issues and PRs
> 
> https://discuss.hypermode.com/t/comparing-two-predicate-counts-in-a-filter/5955
> 
> 
> \### Links to examples and research
> 
> \_No response\_
> 
> \### Additional Information
> 
> \_No response\_

@kesor feel free to add comments and data example to the enhancement request. Thanks.

---

<div class="post-metadata">

**Author:** ![Raphael](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/raphael/32/10075_2.png) [@Raphael](https://discuss.dgraph.io/u/Raphael)\
**Post date:** [January 30, 2023, 5:48pm UTC](https://discuss.dgraph.io/t/comparing-two-predicate-counts-in-a-filter/5955/10 "2023-01-30T17:48:00Z")

</div>

I created a parent node with groupA and groupB relationships.  
Finding the parents with the same number of groupA and groupB relationships can be achieved with

```auto
{
    var(func: type(Parent)) {
      a as count(groupA)
      b as count(groupB)
      c as math(b-a)
     }
    r(func:uid(c)) @filter(eq(val(c),0)){
        name val(a) val(b) val(c)
    }
}

```

Could you tell me if this approach is working for you ? If not, what’s the detail in the use case preventing you from using this simple counting approach ?
