Hi,
I am trying to fetch all the children of a given node. I read through the documentation and it seems like recurse would be something that I want to use but after much hit and trial I am not able to figure it out.
In particular, I want to get all child nodes (via isSubsidiary edge) of a node such that enitity_id=“1”.
I have the entity_id and isSubsidiary (with reverse edge) predicates in my dgraph instance as follows:
1<-2<-3<-4
^
|
5
^
|
6
(Please, don’t mind my ascii art skills.)
And I am expecting my result set to contain the entity_ids [1,2,3,4,5,6] as they all belong to the same tree (1’s children’s tree). Any help would be greatly appreciated.
The above query returns the path from “05QXVL-E” to “0FPWZZ-E”. But I only need “0FPWZZ-E”
in the result set and not the whole path. Is there a way to do that? Thanks for your help so far.
@MichelDiz Thanks for the quick response. It seems the query you posted above prints all nodes of the path except the starting one. But what I need is just the ultimate parent. That is, “0FPWZZ-E”. In particular, consider the following snippet:
Wha you can do is or loop through the arrays levels in your client side. Or do something like this below and loop for the last value from the list. But isn’t guarantee that the sorting order will be always the same. Although normalize directive usually will do the same order from the previous format of the recurse query.
This is weird. Sounds like a nice bug feature tho. Nice finding!
It seems to me that when using the alias for UID, you have in some way forced the value of entity_id to be inserted into this. The rule is that UID must be unique per block, maybe this has bumped into this premise. You have recategorized entity_id to be uid. In all blocks it have been renamed to UID. And when it came time to use @normalize Dgraph overwritten all values as ‘uid’ block by block until get the final nested block.
That’s just a theory. If you do uid : uid you gonna have the same result but will come only (the desired one) the UID from the last nested block. That’s nice!
I assume you are not surprised with the second result, but I surely am. Is there any workaround via which
I can operate on the ultimate_parent uids instead of flattened path in the second block?
If not, then it will require my app to do this in two steps (query ultimate parents and then filter them on some predicate in the second dgraph request) which does not seem ideal. Do you think it can be an acceptable feature request?
Thanks for your help so far.
I’m not cuz the variable tend to maps only UIDs and you can’t pass a value from @normalize as UID map. So from parent_uid would always come a map of UID’s, not values. Unless you wanted a value (but it did not work for uid(X) func).
I think that give @recurse directive a new feature would be good. For the “ultimate parent” giving the last (or multiple last) node of a recurse search. Would be nice to do it without tricks. But not sure how it would be useful for others. Knowing this would be important to allocate a Dev Core for this. Today they are almost 99% working on critical things for next release, features are in last place of importance now. Unless it’s easy to implement and people need it.
One more thing
I think depending on your context it would be worth doing a “tag” to find out who the “ultimate_parent” is.
The idea would be to mark the “ultimate_parent” with a Boolean predicate. That way we can ensure that only it will return from a recursive query. It could even be a Facet.
Today they are almost 99% working on critical things for next release…
Makes sense.
The idea would be to mark the “ultimate_parent” with a Boolean predicate…
I am guessing what you are suggesting here is to generate mutations based on the ultimate_parent uids query’s result set that marks them is_ultimate_parent. And then the queries you suggested below can use that new predicate to filter out the nodes. Correct?
You could create a query that checks whether a node is the last of the chain or not. Maybe a bot or a background task hunting for nodes with this characteristics. If the Node has no children, only parent it is indeed the ultimate at that moment. So you mutate it as "ultimate": "true".
You could use upsert procedure and soon we will have the new transaction #3059. With the new txn this operation would be simpler.
I know this is an old post now, but I figured I’d post my solution for any future viewers.
To get just the ultimate parent, you can store the flat list of uids in a variable, and then filter the results in a second query to only those that don’t have the edge you are recursing on. For Himanshu’s query above:
{
var(func: eq(entity_id, "05QXVL-E")) @recurse(loop:false) {
isSubsidiaryOfFilermstPriorityNoOverlap
x as entity_id
}
ultimate_parent(func: uid(x)) @filter(not has(isSubsidiaryOfFilermstPriorityNoOverlap)) {
entity_id: val(x)
}
}