Math cond on strings

Hello,

I would like to compare string values with the cond keyword in a match function, however, I get an error.
I tried with a string in a variable and with a string literal.

According to the doc, the == operator should work on strings (All types except geo , bool).

Tested on https://play.dgraph.io/ :

{
  var(func:type(Actor), first: 1) {
    nn as name@en
  }
  me(func: type(Actor), first: 10) {
    n as name@en
    test1: math(cond(n == "Sagar Das", 1, 2))
    test2: math(cond(n == nn, 1, 2))
  }
}

I think you misunderstood. The docs state “Types accepted” not “except”. Math works only with numerals.

I’m sorry but it doesn’t seem clear to me.

It is written math functions work with value variables, value variables are said to work with strings and the == operator is said to work on all types except geo and bool, and thus I understood it work with strings.

Maybe it should be better if the math doc explicitly exclude the string type.

Or maybe the cond function could support strings?
However it only makes sense in a few scenarios like testing string equality in a cond.

PS. To be Short

1 - Comparison operators accept Strings as the docs state. But it can’t compare one to many block relations. Only one to one (limit your query to first: 1 in both blocks and you’ll see). Internally when two queries have a one to many relation, it changes the internal variable type. And it is like comparing a single String type to a List String type. So that throws an error.
2 - We should have a custom var to hold variables like a string at least.
Your query should look like this:

{
  var(func:type(Actor), first: 1) {
    nn as name@en
  }
  me(func: type(Actor), first: 10) {
    n as name@en
    _V as String("Sagar Das")
    test1: math(cond(n == _V, 1, 2))
    test2: math(cond(n == nn, 1, 2))
  }
}

3 - Or math and cond functions should accept string type in their placeholders.

Continuing

Yeah, but each operator has its owns rule. So supporting a value variable doesn’t mean that it will support any type of variable in any circumstances.

The main problem relies on the placeholder support. Dgraph doesn’t support strings in the placeholder. So, in that case, you should use an extra variable to hold that string. But we don’t have anything like that. We use math (e.g mynumber as math(1)) to hold numbers, but we don’t have a custom var to hold strings or whatever other types. I talk about it here Custom Block - Discussion

The “hack” would be to record the value on the DB and use it in a variable.

It does support but not when it changes the type. That’s something complex. Maybe a loop could solve that issue.

You can reproduce the string support with

{
  var(func:type(Actor), first: 1) {
    nn as name@en
  }
 A as var(func: type(Actor), first: 10) {
   n as name@en
}
  me(func: uid(A)) {
    test1: math(n == nn)
  }
}

Also, I never saw any docs, test files, or users trying this. Comparing strings at the math level. That’s a bit hacky per see. In fact, I think that normal blocks to check this would be better. Also I think you can get bool results from the len() func.

1 Like

Thank you Michel for the detail explanation, it make sense now for me.
I ended up using block as you suggest.