Getting result from an upsert

Moved from GitHub pydgraph/102

Posted by robin-snt:

When doing an upsert, it is not clear how to get the result of the upsert.

E.g:

def upsert(client, name, state):
    q = """query q($name: string)
    {
        NODE as q(func: eq(name, $name)) {
            expand(_all_)
        }
    }"""

    txn = client.txn()
    state['uid'] = 'uid(NODE)'
    m = txn.create_mutation(set_obj=state, cond='@if(eq(len(NODE), 1))')
    request = txn.create_request(query=q,
                                 mutations=(m,),
                                 variables={'$name': name},
                                 commit_now=True)

    try:
        result = txn.do_request(request)
    finally:
        txn.discard()

It would seem intuitive to have the newly changed state accessible in result.json, but reading this attribute returns b''.

What’s the intended way of getting the newly updated state? Make a new query? That would seem redundant to me, but perhaps there are good reasons to have the user explicitly make a new query.

Upon further contemplation, you could simply return state as that should be your updated data, but then it is unclear how to idiomatically check if the request caused a write to the db.

EDIT: Updated example with setting uid, but the issue still persists.

martinmr commented :

You can’t change uids so I suggest using another field in your example.

I am not very familiar with upsert but I’ll try to answer. I’ll make sure @mangalaman93 takes a look in case I miss something.

Taken from the example in https://docs.dgraph.io/mutations/#upsert-block, an upsert mutation will have a field called uids that contains the uids of the nodes that changed in your query.

If the transaction is committed successfully and the uid of the node you are interested is in this field, then you know that at the point of the commit the state of the node is whatever you set it to in the transaction. The state of the node itself is not returned as that could potentially be a lot of data.

If the uid of the node you were trying to change is not in this field, then the node was not touched so you would need to run a query to get its current state.

robin-snt commented :

I thought I had already tried this method, but I will try again. Thanks for your input @martinmr .

mangalaman93 commented :

We currently do not return the new state of the database after the upsert. This requires committing the transaction, and sending another query to the database to get the updated result. The reason we do this is, the result of query would be different depending upon whether the mutation/upsert was committed.

We recently made a change that is available in the master branch in the PR Remove duplicate code for query processing by mangalaman93 · Pull Request #4269 · dgraph-io/dgraph · GitHub, that returns the result of the query before the mutation was executed.

I think @martinmr is referring to the PR https://github.com/dgraph-io/dgraph/pull/4145. This change was removed in this PR Remove duplicate code for query processing by mangalaman93 · Pull Request #4269 · dgraph-io/dgraph · GitHub.

You could access the latest docs at https://docs.dgraph.io/master/mutations/#upsert-block

robin-snt commented :

@mangalaman93 So currently there is no way of knowing if the upsert caused a write, apart from making a new query?

mangalaman93 commented :

Correct. You could get some sense from the result of the query on previous state of the database. But the full proof approach would be to just query after committing the upsert/mutation.

robin-snt commented :

Thank you so much for your reply and help. Please state this explicitly in documentation.

mangalaman93 commented :

We do mention it explicitly in the documentation of the master branch.