Query Process
To understand how query execution works, look at an example.
{
me(func: uid(0x1)) {
rel_A
rel_B {
rel_B1
rel_B2
}
rel_C {
rel_C1
rel_C2 {
rel_C2_1
}
}
}
}
Let’s assume we have 3 Alpha instances, and instance id=2 receives this query. These are the steps:
- This query specifies the exact UID list (one UID) to start with, so there is no root query clause.
- Retreive posting lists using keys =
0x1::rel_A
,0x1::rel_B
, and0x1::rel_C
.- At worst, these predicates could belong to 3 different groups if the DB is sharded, so this would incur at most 3 network calls.
- The above posting lists would include three lists of UIDs or values.
- The UID results (id1, id2, …, idn) for
rel_B
are converted into queries forid1::rel_B1
id2::rel_B1
, etc., and forid1::rel_B2
id2::rel_B2
, etc. - Similarly, results for rel_C will be used to get the next set of UIDs from posting list keys like
id::rel_C1
andid::rel_C2
.
- The UID results (id1, id2, …, idn) for
- This process continues recursively for
rel_C2_1
as well, and as deep as any query requires.
More complex queries may do filtering operations, or intersections and unions of UIDs, but this recursive walk to execute a number of (often parallel) Tasks
to retrieve UIDs characterizes Dgraph querying.
If the query was run via HTTP interface /query
, the resulting subgraph then gets converted into JSON for
replying back to the client. If the query was run via gRPC interface using
the language clients, the subgraph gets converted to
protocol buffer format and similarly returned to the client.