Reputation: 12737
In my graph, a user is connected to many items and each item can be recursively divided into many sub-items. Since my items have a particular ordering, I'm considering these two options to model my data:
Now I want to create a query to retrieve two levels of items for a given userID. This AQL is my first attempt:
for itemId in (for b in board filter b._from == @_from sort b.order return b._to)
for item1 in (for t in item filter t._id == itemId return keep(t, '_id', 'title'))
return merge(item1, {board: (
for itemId2 in (for b in board filter b._from == item1._id sort b.order return b._to)
for t in item filter t._id == itemId2 return keep(t, '_id', 'title')
)})
The query works and it outputs a result like this:
[
{
"title": "item 1",
"_id": "item/41260117498",
"board": [
{
"title": "item 4",
"_id": "item/42205736442"
},
{
"title": "item 5",
"_id": "item/42208423418"
}
]
},
{
"title": "item 2",
"_id": "item/41260772858",
"board": []
},
{
"title": "item 3",
"_id": "item/41883233786",
"board": []
}
]
Which is fine, but I feel like my query is unnecessarily complex for such a simple traversal. Could someone help me to create a better one, please?
Upvotes: 0
Views: 77
Reputation: 6067
The point in using a graph database is utilize its graph querying capabilities letting it handle the edges, and not to do it on your own by manually joining the edges.
I will demonstrate the pattern matching traversals for such a query; they handle the transision over the edges (_from
and _to
) transparently under the hood for you.
First you would create a graph to configure your edge relations, we use an anonymous graph for simplicity. You have the edge collection board
and the vertex collections user
and item
.
First you simply let run the whole query to get a feeling for how it works, and inspect the full result:
FOR v, e, p IN 1..3 OUTBOUND 'user/andy' board RETURN {v: v, e: e, p: p}
You see that you only need to specify the start node, and the edge collection board
, it will find the vertex collections to query on its own by inspecting the edges.
Now we may add FILTER
s to omit edges and vertices that we don't like:
FOR v, e, p IN 1..3 OUTBOUND 'user/andy' board
FILTER e.title == 'item 2'
FILTER p.edges[1].title != 'item 1'
RETURN {v: v, e: e, p: p}
The example contains two FILTER
instructions; one is matching each edge to have the title
attribute being equal "item 2"
, the other is matching that the first edge in the traversal has to contain title
"item 1"
.
Finaly we use document manipulation to only get the parts of the documents we like:
FOR v, e, p IN 1..3 OUTBOUND 'user/andy' board
FILTER e.title == 'item 2'
RETURN {v: v, e: {title: e.title, _id: e._id}, pathEdgeTitle: p.edges[*].title}
Upvotes: 1