Upsert with multiple UIDs

I’m not sure how to setup a Gist for a Dgraph query, but you can reproduce it with these steps:

First, run this alter on the schema:

type Products { 
    products: [Product] 
} 
type Product { 
    productId: string 
    options: [Option] 
} 
type Option { 
    optionId: string 
    color: string 
}
<collectionId>: int @index(int) .
<color>: string .
<optionId>: int @index(int) .
<options>: [uid] .
<productId>: int @index(int) .
<products>: [uid] .

Then, run this mutate:

{
  "set":[ {
    "uid": "_:products",
    "dgraph.type": "Products",
    "collectionId": 1,
    "products": [
      {
        "dgraph.type": "Product",
        "uid": "_:product",
        "productId": 19610626,
        "options": [
          {
            "dgraph.type": "Option",
            "uid": "_:option",
            "optionId": 32661491,
            "color": "red"
          }
        ]
      }
    ]
}]
}

Then, run this Java code:

String query = "{\n" +
            "  getVals(func: has(products)) {\n" +
            "    productsUid as uid\n" +
            "    products @filter(eq(productId, 19610626)) {\n" +
            "      productUid  as uid\n" +
            "      options @filter(eq(optionId, 32661491)) {\n" +
            "        optionUid as uid\n" +
            "      }\n" +
            "    }\n" +
            "  }\n" +
            "}";

DgraphProto.Mutation mu =
            DgraphProto.Mutation.newBuilder()
                    .setSetNquads(ByteString.copyFromUtf8("uid(productsUid) <products> uid(productUid) ."))
                    .setSetNquads(ByteString.copyFromUtf8("uid(productsUid) <dgraph.type> \"Products\" ."))
                    .setSetNquads(ByteString.copyFromUtf8("uid(productUid) <productId> \"19610626\" ."))
                    .setSetNquads(ByteString.copyFromUtf8("uid(productUid) <options> uid(optionUid) ."))
                    .setSetNquads(ByteString.copyFromUtf8("uid(productUid) <dgraph.type> \"Product\" ."))
                    .setSetNquads(ByteString.copyFromUtf8("uid(optionUid) <color> \"blue\" ."))
                    .setSetNquads(ByteString.copyFromUtf8("uid(optionUid) <dgraph.type> \"Option\" ."))
                    .setSetNquads(ByteString.copyFromUtf8("uid(optionUid) <optionId> \"32661491\" ."))
                    .build();
    Map uidsMap;
    try(DgraphConnection dgraphConnection = DGraphQueryHelper.createDgraphClient(false, context)){
        Transaction txn = dgraphConnection.getDgraphClient().newTransaction();
        try{
            DgraphProto.Request request = DgraphProto.Request.newBuilder()
                    .setQuery(query)
                    .addMutations(mu)
                    .setCommitNow(true)
                    .build();
            DgraphProto.Response res = txn.doRequest(request);
            uidsMap = res.getUidsMap();
            String exactOutput = res.getJson().toStringUtf8();
        } catch (Exception e){
            throw e;
        }
        finally {
            txn.discard();
        }

    } catch (Exception e){
        logger.error("The message on the exception is: " + e.getMessage());
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        logger.error("Showing stack trace: " + sw.toString());
        throw e;
    }

The spacing got messed up a little when I pasted the code, but I don’t think it has any syntax errors.

I meant a github gist like so upsert test · GitHub
So, this upsert block is working great. No errors. It might mean that some typo in your Java Code is happening. As I don’t know Java I can’t tell what is it.

1 Like

Could there be a bug in the Java Dgraph client?

I just noticed that there was more information in the exception that was thrown. It stated:

io.grpc.StatusRuntimeException: UNKNOWN: while parsing query: . . . Some variables are defined but not used
Defined:[optionUid productUid productsUid]
Used:[optionUid]

Why would it be saying that only optionUid was used? That seems odd to me.
I wonder if @amanmangal would have more ideas about this because he’s one of the Java client maintainers.

You should only call .setSetNquads once in the Mutation builder. As you currently have it, only the last setSetNquads call is ultimately applied, which is why the error says only optionUid is used.

2 Likes

That’s the issue! Thanks for the help!

Now, is there a way for me to be able to get the UIDs back out of the upsert? Or, will I need to run a second query to do that?
(I’m referring to this line: uidsMap = res.getUidsMap(), which is currently empty.)

it is empty cuz, for now, there’s no response for existent entities. Only returns UIDs when you create new entities/nodes.

1 Like

You guys are awesome. Thanks for the help.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.