How to find nodes that have no inbound edges from other nodes?

I am struggling to find how to search for all “root” nodes.

For example, I have Node and each Node has an edge called Links which is a list of other Nodes. What would be a way to find all Nodes that are not being linked from any other Node?

You could do it by adding the @reverse directive to the Links predicate as well as a count index.

Then you can query the nodes with no incoming edges like:

{
  root_nodes(func: eq(count(~Links), 0)) {
    uid
  }
}

However, keep in mind that adding reverse links and a count index have performance implications for mutations (since the count index must be maintained and each mutation now adds two edges instead of one).

You could also do it by adding only the reverse edges (not the count index because it’s more expensive to maintain this index than to add reverse edges) and running the following query (this query implies you have marked all the Node types using the type system):

{
   incoming_count(func: type(Node)) {
    A as count(~Links)
  }
  
  root_nodes(func: uid(A)) @filter(eq(count(A), 0))  {
    uid
  }
}

One last option option would be to query all the Node nodes, their links, and doing the calculation in your application. This involves doing more work on your end but does not require adding additional indices or reverse edges. If this type of query is not meant to be run regularly, I’d advise against adding additional indices.

Links to relevant sections of the docs:

Indices (including count): https://docs.dgraph.io/query-language/#count
Reverse edges: https://docs.dgraph.io/query-language/#reverse-edges
count queries: https://docs.dgraph.io/query-language/#count

docs for the type system: https://docs.dgraph.io/query-language/#type-system