Python, upsert and cryptic error

Report a Dgraph Client Bug

What Dgraph client (and version) are you using?

(put “x” in the box to select)

  • Dgo
  • PyDgraph
  • Dgraph4J
  • Dgraph-js
  • Dgraph-js-http
  • Dgraph.NET

Hi

I dont think this is a bug, its more likely that its an issue with my lack of understanding.

Objective

I’m trying to save an object, but want to check that it exists first, and if not, then persist it - eg, an upsert.

I’m basing my code on what is on https://dgraph.io/docs/clients/python/#running-a-conditional-upsert
My modification is basically to include a variable.

The following method throws an error, and unfortunately the error message is rather cryptic.

        def get_by_name_type(self, name: str, txn):
            query = """
            query all($a: string) {
                {
                  u as var(func: eq(name, $a))
                }
            }
            """
            nquad = f"""
              uid(u) <name> "{name}" .
              uid(u) <dgraph.type> "Skill" .
            """
            variables = {'$a': f'{name}'}
            cond = "@if(eq(len(u), 0))"
            mutation = txn.create_mutation(cond=cond, set_nquads=nquad)

            request = txn.create_request(query=query, variables=variables, mutations=[mutation], commit_now=True)
            response = txn.do_request(request)
            print(response)

Error

<_InactiveRpcError of RPC that terminated with:
	status = StatusCode.UNKNOWN
	details = "line 2 column 16: Expected some name. Got: lex.Item [6] "{" at 2:16"
	debug_error_string = "{"created":"@1623205185.254896051","description":"Error received from peer ipv6:[::1]:9080","file":"src/core/lib/surface/call.cc","file_line":1066,"grpc_message":"line 2 column 16: Expected some name. Got: lex.Item [6] "{" at 2:16","grpc_status":2}"
>

Question

Is anyone able to point out where I’m going wrong?

This query doesn’t make sense for me(right?). Looks like an update, but you are quering for the var “name” and in the update you are using the same var “name”(that will be $a) hoping to change something? Also, I’m not sure if using the code variable instead of DQL variable would be safe to use.

The correct use would be

            query = """
            query all($a: string) {
                {
                  u as var(func: eq(name, $a)) { NM as name)
                }
            }
            """
            nquad = f"""
              uid(u) <name> "val(NM)" .
              uid(u) <dgraph.type> "Skill" .
            """

Show what is printed in that varible called “name” both in the query and in the body of the nquad variable.

Cheers.

Upsert should mean insert or update.

If the query returns no result, it should insert it. That is the objective.

I’ve used code variables (f strings) in other places without any issue.

Yeah, I think you don’t understand what I meant. Your usage is “biased”. It will never update nothing, it will keep the loop of the same information over and over. As you are using the same variables. That’s the point.

PS. But yeah, with the cond and the upsert logic, that would be ignored for sure. So the issue must be the value in the variable.

So, print what is inside that variable so we can tell if it is related with formatting or something.

It would be fine if it actually did that. However its not even inserting.

The below is the query and nquads with variable substitution.

Query


            query all($a: string) {
                {
                  u as var(func: eq(name, $a))
                }
            }
            

nquad

uid(u) <name> "DOCKER" .
uid(u) <dgraph.type> "Skill" . 

Not sure what is happening, have you isolated the context? e.g. tested in JS or Go?

No, I havent tried that approach.

I think it may be related to the scope of the transaction, as there are other mutations using the same transaction happening before and after this method is called, but havent confirmed this theory yet.

I’ll do some experiments and let you know what I find.