Search code examples
arangodbarangojs

ArangoDB populate relation as field over graph query


I recently started using Arango since I want to make use of the advantages of graph databases. However, I'm not yet sure what's the most elegant and efficient approach to query an item from a document collection and applying fields to it that are part of a relation. I'm used to make use of population or joins in SQL and NoSQL databases, but I'm not sure how it works here.

I created a document collection called posts. For example, this is a post:

{
  "title": "Foo",
  "content": "Bar"
}

And I also have a document collection called tags. A post can have any amount of tags, and my goal is to fetch either all or specific posts, but with their tags included, so for example this as my returning query result:

{
  "title": "Foo",
  "content": "Bar",
  "tags": ["tag1", "tag2"]
}

I tried creating those two document collections and an edge collection post-tags-relation where I added an item for each tag from the post to the tag. I also created a graph, although I'm not yet sure what the vertex field is used for.

My query looked like this

FOR v, e, p IN 1..2 OUTBOUND 'posts/testPost' GRAPH post-tags-relation RETURN v

And it did give me the tag, but my goal is to fetch a post and include the tags in the same document...The path vertices do contain all tags and the post, but in separate arrays, which is not nice and easy to use (and probably not the right way). I'm probably missing something important here. Hopefully someone can help.


Solution

  • You're really close - it looks like your query to get the tags is correct. Now, just add a bit to return the source document:

    FOR post IN posts
        FILTER post._key == 'testPost'
        LET tags = (
            FOR v IN 1..2 OUTBOUND post
                GRAPH post-tags-relation
                RETURN v.value
        )
        RETURN MERGE(
            post,
            { tags }
        )
    

    Or, if you want to skip the FOR/FILTER process:

    LET post = DOCUMENT('posts/testPost')
    LET tags = (
        FOR v IN 1..2 OUTBOUND post
            GRAPH post-tags-relation
            RETURN v.value
    )
    RETURN MERGE(
        post,
        { tags }
    )
    

    As for graph definition, there are three required fields:

    • edge definitions (an edge collection)
    • from collections (where your edges come from)
    • to collections (where your edges point to)

    The non-obvious vertex collections field is there to allow you to include a set of vertex-only documents in your graph. When these documents are searched and how they're filtered remains a mystery to me. Personally, I've never used this feature (my data has always been connected) so I can't say when it would be valuable, but someone thought it was important to include.