Upsert should always return the uid
pepoospina opened this issue · 3 comments
Experience Report
What you wanted to do
I am using an upsert operation as described in dgraph-js to get or create a new node with a given external id called did
and return its uid
.
What you actually did
This is my code. It works the first time the node with the external id did
does not exist. But it fails if it does exist.
const mu = new dgraph.Mutation();
const req = new dgraph.Request();
let query = `profile as var(func: eq(did, "${did}"))`;
req.setQuery(`query{${query}}`);
let nquads = `uid(profile) <did> "${did}" .`;
nquads = nquads.concat(`\nuid(profile) <dgraph.type> "${PROFILE_SCHEMA_NAME}" .`);
mu.setSetNquads(nquads);
req.setMutationsList([mu]);
req.setCommitNow(true);
let response = await this.client.newTxn().doRequest(req);
let uid = response.getUidsMap().get("uid(profile)")
return uid;
Why that wasn't great, with examples
I will have to add new logic to my function to consider the case in which the result is empty and run a new query to get the uid
of that did
.
I don't like how that if
looks inside my function. Is that a code smell? Should the upsert return the uid
even if it did not create it?
This is my updated function
const mu = new dgraph.Mutation();
const req = new dgraph.Request();
let query = `profile as var(func: eq(did, "${did}"))`;
req.setQuery(`query{${query}}`);
let nquads = `uid(profile) <did> "${did}" .`;
nquads = nquads.concat(`\nuid(profile) <dgraph.type> "${PROFILE_SCHEMA_NAME}" .`);
mu.setSetNquads(nquads);
req.setMutationsList([mu]);
req.setCommitNow(true);
let response = await this.client.newTxn().doRequest(req);
let uid = response.getUidsMap().get("uid(profile)")
if (!uid) {
// it already existed. query for it.
const didQuery = `
query {
profile(func: eq(did, "${did}")) {
uid
}
}
`;
let result = await this.client.newTxn().query(didQuery);
let profile = result.getJson().profile[0];
uid = profile.uid;
}
return uid;
Any external references to support your case
Thanks for your report, @pepoospina
Moving this issue to the dgraphjs repository.
@campoy I am not sure is an issue of dgraph-js. The standard dgraph upsert
operation will not return the uid
if the entry already existed.
@pepoospina We can retrieve UID of the existing node by including uid
to the query part of the upsert operation.
const mu = new dgraph.Mutation();
const req = new dgraph.Request();
let query = `profile as all(func: eq(did, "${did}")) {
uid
did
}`;
req.setQuery(`query{${query}}`);
let nquads = `uid(profile) <did> "${did}" .`;
nquads = nquads.concat(`\nuid(profile) <dgraph.type> "${PROFILE_SCHEMA_NAME}" .`);
mu.setSetNquads(nquads);
req.setMutationsList([mu]);
req.setCommitNow(true);
let response = await dgraphClient.newTxn().doRequest(req);
let uid = response.getUidsMap().get("uid(profile)");
if (uid === undefined) {
uid = response.getJson().all[0].uid;
}
console.log(uid);