What does adding reverse edges really mean? (@reverse)

If you have several people and you want to know “who works with Alice?”, how can you know whether you’re supposed to use ~works_with or works_with in the query? Are you meant to use both?

For example, Bob and Carol work with Alice. From my point of view, I was expecting it would be indifferent whether the works_with edge was created in one direction or the other because the @reverse directive was used on the works_with edge.

Schema:

works_with: uid @reverse .

Using the following data

{
  set {
    _:alice <works_with> :_bob .
    _:carol <works_with> :_alice .
  }
}

I was expecting that a query like

{
  alice_coworkers(func: eq(name, "Alice")) {
    name@.
    works_with {
      name@.
    }
  }
}

would return both Bob and Carol, but that is not the case, it only returns Bob. In order to obtain the desired results to the question “who works with Alice?”, either the query must be modified to include ~works_with, i.e.,

{
  alice_coworkers(func: eq(name, "Alice")) {
    name@.
    works_with {
      name@.
    }
    ~works_with {
      name@.
    }
  }
}

Or the data must be expanded to explicitly include the edge in the opposite direction:

{
  set {
    _:alice <works_with> :_bob .
    _:alice <works_with> :_carol .

    _:carol <works_with> :_alice .
    _:bob <works_with> :_alice .
  }
}

However, this is what I was expecting the @reverse directive to do, so, what’s the difference between this last approach and what @reverse really does?

Thanks

It just adds an edge in the reverse direction to what the original NQuad specified.

_:alice <works_with> _:bob .
_:carol <works_with> _:alice .

For the mutation above, you could assume that it will add the following edges (in reality we don’t have a ~works_with predicate).

_:bob <~works_with> _:alice .
_:alice <~works_with> _:carol .

Therefore, _:alice + ~works_with doesn’t return bob.

I think the reverse edges are easier to reason for parent-child relationships where it is clear what predicate to use while querying. For e.g. child and ~child = parent. For your use-case, you’d be better off adding the edges manually in both directions so that you can just traverse works_with edge.

_:alice <works_with> _:bob .
_:carol <works_with> _:alice .

_:bob <works_with> _:alice .
_:alice <works_with> _:carol .

Or if you wish to use the @reverse directive, then you query for both works_with and ~works_with.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.