I have a schema in which one node references another, and sometimes when I query that node I get an array instead of a single string response. Unfortunately, lot of code will break if the value is sometimes a string and sometimes not. I’m not sure I can work around this, so I’d like to understand what scenarios may cause it so I may try to avoid it entirely. I’d say it happens about half the time.
Schema:
type Foo {
bar
}
bar: uid .
type Bar {
bar_name
}
bar_name: string @index(exact) .
It doesn’t look like this is always happening (based on the demo script anyway).
Ok, I can work with this, or anything where it’s always one or the other.
I’m using 116 to assign the value of the bar3 query to the bar uid predicate, replacing the previous bar2 uid that was set there in line 84.
I’m not sure what you mean about line 125. I’m looking up every Foo to print its results (although there’s only one). The foo variable is out of scope at that point as the request that defined it was run on line 123.
I don’t know, running the script multiple times gives different output for the bar_name predicate. Do you see a problem in the loop?
mu.setSetJson({
'bar': [{'uid': 'uid(bar2)'}], #be careful here, make sure it is ONE to ONE
'dgraph.type': 'Foo',
});
As bar is an Edge connecting to another object. This feels like a bug. But for now, fix the syntax to the one I mentioned above.
Do you really need to pass 'dgraph.type': 'Foo' all the time? You should add it in the creation, not in an upsert. But if you are creating it during the upsert, It is fine. Just a small thing, not important.
Line 99
I’m not sure what you are doing in that line. You say “Switch to bar 3” is it a migration of nodes to other references? You should unlink the others if it is a migration.
Fix the syntax there.
Also, if you have a lot of foos foo as var(func: type(Foo)) you will link them all in that upsert. That might be there the issue.
Maybe is the mutation syntax. Check it and let me know.
I haven’t (until now) tried mutating the predicate using an array in setJson. I wouldn’t have expected it to work. However, the results are the same with all four options below:
mu.setSetJson({
bar: 'uid(bar2)',
});
mu.setSetJson({
bar: {uid: 'uid(bar2)'},
});
mu.setSetJson({
bar: ['uid(bar2)'],
});
mu.setSetJson({
bar: [{uid: 'uid(bar2)'}],
});
That is, I sometimes get an array response to the query in postCommit and sometimes not.
No not in this case, it’s just habit on my part. A long while back I had forgotten it in a few places and a lot of stuff broke so now I’ve just been explicit every time.
I don’t know what you mean – I’m trying to replace the value in the predicate. Do I need to do a delete mutation and then a set mutation whenever I want to replace a value in a scalar/uid predicate?
Yeah – in this case, I have one, so I could make a (mostly) minimally reproducible demo. I’m more explicit in my real code.
For now I guess I just need to check to see if the result is an array instead of the expected string and retry the query. This is concerning, though, because I don’t know how many retries I will need to run (and how long I’ll need to make users wait), but it is a workaround.
Btw, for future readers: removing the dgraph.type set in the preCommit function (in the gist) didn’t change the result – the query still sometimes returns a string and sometimes returns an array.
@MichelDiz I may have found a workaround, and I think this might mean there’s a bug. If I change my queries to:
query {
foo(func: type(Foo)) {
uid
bar {
uid <-- Added this
bar_name
}
}
}
the bar_name result in Pre-Commit is always a string:
You’ll see a similar result if you remove bar_name entirely and just query bar { uid } or bar { count(bar_name) } – basically any time you specify only one predicate or function in the braces.