I wanted to implement a small support ticket system with ArangoDB. I created a collection ticketcategories and wanted to nest them using edges, so I created an edge collection and a graph.
To visualize this, here's an example of the structure:

And I'd like to return this into a nested object so I can display it in a combobox later, i.e. like this:
{
root: {
categories: [
bug: {
categories: [...]
},
content: {
categories: [
product: {...}
]
},
feature: {...}
]
}
}
From what I've seen this is not possible with pure AQL, but I don't have much experience with Arango, so I might be wrong.
I tried to perform a normal graph traversal like so:
FOR v, e, p IN 1..4
OUTBOUND 'ticketcategories/root'
GRAPH TicketCategorySubcategories
OPTIONS { order: 'bfs' }
RETURN p
Since that would give me all paths, but merging those together into a nested object in TypeScript seems dirty. And simply returning the vertices won't give me the relations, so I don't know which subcategories belong to which categories...
Hopefully someone has an idea.
First, returning
p(the path) will give you all edges and vertices, so it is possible to determine the relations in JS. However, AQL is good at finding and collecting data, but not great at building a specific JSON document, so the "inelegant" JS could actually be the easiest/cleanest method.As with any declarative query language, creativity is often required.
My normal approach is to first do it the "stupid" way (very literal/static) and then iterate once you understand how everything fits together and your output is correct.
This example is very static (your graph schema won't change), stepping through the graph one hop at a time. Here, I'm using
ZIP()to combine the attribute names to the content in a dynamic way. I know this won't replicate your example JSON schema (it may not even work properly), but it should be illustrative:I've used an attribute (
v.type) to determine the ticket category/area/reason, but this could be done via collection as well (different collections for each category):Or it could be done via an edge property:
If you have unique
typevalues, another way to do this could be with theCOLLECTstatement and aggregation:How you define different document types can change your query approach dramatically. For instance, if you have an attribute on each vertex/document, it makes it easy to filter for that. But if you have the definition baked into edges, then you have to query the edges before grabbing the vertices. Either approach isn't bad, just different.
Generally, I have found that when I need to produce a complex JSON document, it's best to use a Foxx service, or at least in-app code with several AQL queries. It's a LOT easier to understand the logic and offers much more control and flexibility.