Search code examples
arangodbaql

ArangoDB - Swap _to and _from values for edge using AQL


Is there a clean way to swap the _to and _from values for an edge using AQL? According to Arango's documentation on Edges:

To change edge endpoints you would need to remove old document/edge and insert new one. Other fields can be updated as in default collection.

So what I was able to come up with was a query that looks like this:

FOR edge IN edge_collection
    FILTER [some criteria]
    LET tempEdge = KEEP(edge, ATTRIBUTES(edge, true))
    LET newEdge = MERGE([{'_key':edge._key}, {'_from':edge._to}, {'_to':edge._from}, tempEdge])
    REPLACE newEdge IN edge_collection
    RETURN NEW

To explain my own solution a bit, I used the ATTRIBUTES(edge, true) function to get the names of all of the Attributes on the Edge, and the true parameter removed the internal attributes (like _key, _id, _to, etc.). Read more about ATTRIBUTES here.

Then the KEEP(edge, [attributes]) function returns a new Document that only has the Attributes specified in the given array, which thanks to the ATTRIBUTES function in this case, is everything but the internal fields. Read more about KEEP here.

Then I use the MERGE function to combine the _key from the original edge, swap the _to and _from values, and all of the non-internal attributes. Read more about MERGE here.

Lastly, I use REPLACE which removes the original edge and adds the new one in, just like Arango requires. Read more about REPLACE here.

Like I said, this appears to work, but the MERGE in particular feels like the wrong way to go about doing what I did. Is there an easier way to set values on an Object? For instance, something that would let me just make a call similar to: tempEdge._from = edge._to?


Solution

  • Yes, there is a simpler solution:

    FOR edge IN edge_collection
        FILTER [some criteria]
        UPDATE edge WITH {_from: edge._to, _to: edge._from} IN edge_collection
        RETURN NEW
    

    _from and _to can be updated (in contrast to the system attributes _id, _key and _rev), so you don't need to replace the whole document. And since UPDATE merges the changes into the existing document, you only need to specify the new values for _from and _to.