Is it possible to "inspect" all predicates of a node without having type definitions?

What I want to do

I want to be able to explore a graph. Literally traverse each node and see all the predicates and edges that they have.

What I did

The only solution that I found was to define types and use expand(_all_). That works well as long as the predicates are in the type definitions. But I couldn’t find a way to get ALL the predicates of a node regardless of whether those are defined in a type or not.

Dgraph metadata

I’m using the latest version v21.12

No there is not - the storage is organized by predicate, not ‘node’ so the only way to see all the predicates of a node is to ask the system go to all these predicates and get the value for uid 0x123.

The type system and expand(type) is just shorthand for that format of question. Furthermore, expand(_all_) is just like expand(MyType) but looks up the type arguments for expand() from the value of dgraph.type at each node.

So as a workaround to setting types on every node, you can define a single type AllMyPredicates and use expand(AllMyPredicates) but it has the same performance implications as having every predicate there in your query.

If you use the GraphQL layer the strict typing will tell you exactly what is ‘on a node’ but behind the curtain it just knows which predicates to inspect.

1 Like

Thanks so much for your response.

You can also export the database, and look for your object with grep:
zgrep "^<0xabcdef>" /path/to/g01.rdf.gz
where 0xabcdef is UID of your node.

:grimacing: yea… that would also work.

No types and expand(_all_) needed!

Given the schema of your Dgraph instance, that you can get from Dgraph:

schema {
  predicate
}

You can query for all nodes that contain any of the predicates (to be able to bootstrap and read those uids) and explicitly list all predicates to retrieve their values, if they exist.

Assume my schema contains <name> and <director>, my query would look like:

query {
  name as var(func: has(<name>))
  director as var(func: has(<director>))

  result (func: uid(name, director)) {
    <uid>
    <name>
    <director> { <uid> }
  }
}

For a lot of predicates in your schema or lots of nodes, of course, you would have to split this by predicates and paginate the result. This scales very well. I can elaborate on that if needed. This is how the Spark Dgraph connector partitions an arbitrary large graph and reads it in chunk by chunk. This works for any size of a graph, as long as a single predicate of a single uid fits into single Dgraph query response.