Need help with conditional upsert (DQL)

I have recently started to play around with conditional upsert mutations with DQL and find it a good way for some of my real world projects. Unfortunately, I have problems with understanding how exactly the conditions work. I could also not find any documentation about the syntax of the conditions.

So what I’m trying to do right now is this:

I have a User with the following fields

type User {
  id: ID!
  email: String! @id
  role: Role
  profilePic: ProfilePic
  settings: UserSettings
}

Inside a Dgraph lambda I want to either create or update the user, thus there I’ll either submit the user id or the user email. In either case I want to create/update different fields of the User predicate (for simplicity now, if I update I want to include profilePic and settings, on create I’ll just set the email).

My current JSON object creation inside the lambda looks like this:

const queries = [
    `q1(func: uid(${id || ""})) { v1 as uid \n User.settings { v2 as uid } \n User.profilePic { v3 as uid } }`,
    `q2(func: eq(User.email, "${userUpdates.email || ""}")) { v4 as uid \n User.role { v5 as Role.type } }`,
  ];

  return {
    query: `{ ${queries.join(" \n ")} }`,
    mutations: [
      {
        cond: `@if(eq(len(v1), 1))`,
        set: {
          uid: "uid(v1)",
          ...userPred,
        },
      },
      {
        cond: `@if(eq(len(v2), 1))`,
        set: {
          uid: "uid(v2)",
          ...userSettingsPred,
        },
      },
      {
        cond: `@if(eq(len(v3), 1))`,
        set: {
          uid: "uid(v3)",
          ...profilePicPred,
        },
      },
      {
        cond: `@if(eq(len(v1), 0) AND eq(v5, "STUDENT"))`,
        set: {
          uid: "uid(v4)",
          "User.givenName": "BY EMAIL WITH ROLE",
        },
      },
    ],
  };

Most of it works but unfortunately mutation number 4 with the condition eq(v5, "STUDENT") gives an error

Some variables are defined but not used

Dgraph simply ignores this condition (v5 is not recognised in the condition).

So my question basically is:

  • how do this conditions work?
  • is there a documentation somewhere?

Thanks! Any help appreciated!

Variables are arrays of tuples consisting of an uid and a value. So you need to either extract the uid with uid() or the value with val(). You can also do some aggregations (len(), sum(), ...). So in case with v5, you can compare the extracted value with eq(val(v5), "STUDENT").
https://dgraph.io/docs/query-language/value-variables/

Thanks for your answer!

Unfortunately this did not really work for me and regarding this thread, Dgraph does not support string equals in @if() statements of mutation conditions. However, it is possible to perform an additional match query. So, in order to do something like this

{
  "query": "{ q(func: uid(0x1)) { u as uid \n v as User.status } }",
  "mutations": [
    {
      "cond": "@if(eq(len(u), 1) AND eq(val(v), \"PENDING\"))",
      "set": {
        "uid": "uid(u)",
        "User.status": "ACTIVE"
      }
    }
  ]
}

we would introduce a second query, saved as a variable

{
  "query": "{ q(func: uid(0x1)) { u as uid \n v as User.status } } \n matchPending as var(func: eq(val(v), \"PENDING\"))",
  "mutations": {
    "cond": "@if(eq(len(u), 1) AND eq(len(matchPending),1))",
    "set": {
        "uid": "uid(u)",
        "User.status": "ACTIVE"
      }
  }
}