Math() function does not work in the expected way in a specific scenario

To complement this answer read:

This one would help in some use cases in this post FOREACH func in DQL (loops in Bulk Upsert)

Also, this one would be handy Custom Block - Discussion

PS. Pay attention that any post with tag “discussion” or “proposal” won’t work at all, as it is just a discussion.

About the comments in the Main query

The order of the post is changed. First, read “Main Query” then analyze the “Formatted dataset” and then go back to this part. You can also just jump to the “Final Considerations” if you don’t want to read everything.

Comment: This won’t Number 1

As they are two distinct entities, for some reason Dgraph does not add sums (math func in this case) between two blocks with different entities or even different levels. This requires one more block to combine the two variables. But even tho, some things you wanna do, won’t work.

Comment: This won’t Number 2

As you can see, the “location” variable is not propagated to that block. You should see "loc": 45 in the response, but don’t. That’s a design thing in the query system. I think there are some discussions on that or Github issues. See something like Add a possibility to identify a variable that has not been assigned yet. ("undefined") · Issue #4619 · dgraph-io/dgraph · GitHub

Comment: This won’t Number 3

The aggregation block would be the one indicated, but it only works from 1 to 1. That is, from one entity to another entity. It won’t work from 1 to many. In the case of 1 to many it would add all values of all entities and this is not what is desired for this use case.

Also, I think the “foreach” function I had mentioned in the beginning would help in this case.

e.g:
In the first two blocks, choose only one entity by its UID.

  varr(func: uid(0x1c5631)){  # User entity UID
(...)
  varg(func: uid(0x1c5635)) { # Place entity UID

My example

{    
  var(func: uid(0x1c5631)){
    uid
    location as user.value
}
  var(func: uid(0x1c5635)) {
    uid
    variable as place.value
  }
  varme(){
    var1 as user.value : sum(val(location))
    var2 as place.value : sum(val(variable)) 
    d1 as lt25 : math(var1 - var2 <= 25) 
    gtMinus25 : math(var2 - var1 >= (-25))
    Example1: math(var1 >= 100) 
  }
  
 #This query won't work
  query(func: uid(variable)) @filter(eq(val(d1), true)){
    place.name
    place.value
  }
} 

Response

{
  "data": {
    "varme": [
      {
        "user.value": 45
      },
      {
        "place.value": 100
      },
      {
        "lt25": true
      },
      {
        "gtMinus25": true
      },
      {
        "Example1": false
      }
    ],
    "query": []
  }
}

Also, the values you would have in that block do not work in later blocks e.g: The response value “true” won’t be applied in the filter eq(val(X), true).

Main Query

{    
  varr(func: type(user), first:1){
    location as user.value
}
  varg(func: type(place)){
    variable as place.value
    d1 as lt25 : math(variable - location <= 25) 
    d2 as gtMinus25 : math(variable - location >= (-25))
    checkk: math(location * variable) #This won't Number 1
    va: val(variable)
    loc: val(location) #This won't Number 2
    loc2:  math(1+location) #This won't as  Number 2
    loc3:  math(1) #This works, as there's no var
  }
  varme(){
    checkk: sum(val(location))
    check2: sum(val(variable)) #This won't Number 3
  }
  
  query(func: type(place))@filter(eq(val(d1), false) AND eq(val(d2), true)){
    place.name
    place.value
  }
} 

Response

{
  "data": {
    "varr": [
      {
        "user.value": 45
      }
    ],
    "varg": [
      {
        "place.value": 100,
        "lt25": false,
        "gtMinus25": true,
        "checkk": 0,
        "va": 100
      },
      {
        "place.value": 25,
        "lt25": true,
        "gtMinus25": true,
        "checkk": 0,
        "va": 25
      },
      {
        "place.value": 25,
        "lt25": true,
        "gtMinus25": true,
        "checkk": 0,
        "va": 25
      },
      {
        "place.value": 5,
        "lt25": true,
        "gtMinus25": true,
        "checkk": 0,
        "va": 5
      }
    ],
    "varme": [
      {
        "checkk": 45
      },
      {
        "check2": 155
      }
    ],
    "query": [
      {
        "place.name": "place",
        "place.value": 100
      }
    ]
  }
}

Formatted dataset

{
   "set": [
      {
         "dgraph.type": "place",
         "place.value": 25,
         "place.name": "place"
      },
      {
         "dgraph.type": "place",
         "place.value": 5,
         "place.name": "place"
      },
      {
         "dgraph.type": "place",
         "place.value": 25,
         "place.name": "place"
      },
      {
         "dgraph.type": "place",
         "place.value": 100,
         "place.name": "place"
      },
      {
         "dgraph.type": "user",
         "user.value": 5
      },
      {
         "dgraph.type": "user",
         "user.value": 45
      },
      {
         "dgraph.type": "user",
         "user.value": 45
      },
      {
         "dgraph.type": "user",
         "user.value": 45
      },
      {
         "dgraph.type": "user",
         "user.value": 45
      },
      {
         "dgraph.type": "user",
         "user.value": 45
      },
      {
         "dgraph.type": "user",
         "user.value": 90
      },
      {
         "dgraph.type": "user",
         "user.value": 60
      },
      {
         "dgraph.type": "user",
         "user.value": 6
      },
      {
         "dgraph.type": "user",
         "user.value": 78
      },
      {
         "dgraph.type": "user",
         "user.value": 50
      },
      {
         "dgraph.type": "user",
         "user.value": 35
      }
   ]
}

Final considerations

Many of the things you want to do are not supported by DB. And I believe that a good part of it is perfectly possible to do at the level of the business logic of your application. Implementing each piece of the above case requires time and work to support it and also popularity, not everyone would use the DB like that - If it becomes popular, more chances of someone working on it. So I recommend that you do them in your application.

Cheers.