2

I have a pretty standard graphql which represent a tree structure:

graph

I would like to make a graph traversal and force the order according to the order I set on each edge:

A -> C

A -> B -> E

A -> B -> D

I tried to add a SORT on my query, but it sorts the whole resulting array which is not what I want:

FOR v, e, p IN 1..1000 OUTBOUND A
    edge_collec
    SORT e.order
    RETURN v

Is there a way to do this using AQL?

Tdy
  • 863
  • 12
  • 28
  • As far as I can tell, a different order wouldn't make any difference to the traversal in the provided example. Thus, I wonder if you could sort the results client-side instead. Doing certain things on the server-side can be problematic, see the discussion about [enumerating results](https://github.com/arangodb/arangodb/issues/5359). What controls the order in which edges are traversed is the doubly-linked list of the [hybrid index](https://www.arangodb.com/2016/04/index-free-adjacency-hybrid-indexes-graph-databases/) I suppose (newest edges last?) – CodeManX Nov 28 '18 at 17:24
  • How did you want to control the sorting? It looks like in the above example you are sorting the by the name of the last vertex in the path, sorted descending? Remember that the result from your `FOR v, e, p` query above will be three arrays, and you probably want to look at saving the `p` result to a variable and then execute additional queries over that. But you'll need to be familiar with the contents of `p` as it contains paths, which are collections of vertices and edges. – David Thomas Nov 28 '18 at 23:42
  • Please include the expected results and the actual results using your letters example. If I understand you correctly, you expected ACBED but got CEABD? – TZubiri Nov 29 '18 at 07:18
  • @CoDEmanX It would make a difference, if the traversal were to visit edges of order 0 first, then it would always visit C before B. Otherwise the order is undefined. Furthermore for the purposes of result sorting, the client doesn't have enough information to know whether E or C should come first. – TZubiri Nov 29 '18 at 07:20
  • @DavidThomas Are we seeing the same query? I see that he is sorting by an attribute of the edge. And that he is returning only the vertex, not the edges and vertices. – TZubiri Nov 29 '18 at 07:24
  • @TomasZubiri The traversal gives me BDEC, I want to force CBED. The query I put here with the `SORT` is incorrect as it gives me CEBD. – Tdy Nov 29 '18 at 09:00
  • 1
    It works as intended, it sorts by `order` after the traversal. C and E both have _order: 0_, B and D _order: 1_, thus C and E are sorted before B and D. Note that the possible return results are CEBD, ECBD, CEDB and ECBD. You should try `SORT LENGTH(p.edges), e.order` to first sort by path length and by _order_ attribute secondly (for equally long paths). That should give you CBED. – CodeManX Dec 03 '18 at 09:34
  • 1
    @CoDEmanX Yep `SORT LENGTH(p.edges), e.order` makes the job. Probably the simplest solution. Feel free to write a proper answer to get the credit – Tdy Dec 05 '18 at 11:20

1 Answers1

3

What the query does is:

  • Follow all outgoing edges in edge collection edge_collec from start vertex A
  • Then sort in ascending order by edge attribute order
  • Return the vertices (the last vertex of each found path)

The edge attribute e.order is either 0 or 1:

  • A --[ order: 1 ]--> B
  • A --[ order: 0 ]--> C
  • B --[ order: 1 ]--> D
  • B --[ order: 0 ]--> E

Sorting by order will return C and E (0) before B and D (1). Because two edges have the same value, it's undefined whether C or E is returned first, and whether B or D is returned third.

If you want the vertices at depth = 1 to be returned before the vertices at depth = 2, but still sort by order on each depth level, you can use:

SORT LENGTH(p.edges), e.order

LENGTH(p.edges) gives you the current depth of the traversal. It first sorts by depth, then by the edge attribute and will give you the desired result order: C B E D

CodeManX
  • 11,159
  • 5
  • 49
  • 70