Traverse up in ArangoDB

102 Views Asked by At

I am trying to learn ArangoDB with PHP. I currently have the following graph set up:

User -> userEmail -> Email

'User' and 'Email' are vertex collections and 'userEmail' is an edge collection.

I am using this model for user authentication where upon request, the code would match the given email against the database, fetch that node and return the incoming 'userEmail' edge and 'User' node but only if the property 'primary' is set to 'TRUE' in the 'userEmail' edge.

Current Solution

I am using the following as a current solution, but I don't think this is the best way of achieving what I desire. It also does not give me a way to detect the 'primary' field on the 'userEmail' edge

FOR e IN email
    FILTER e.address == @email
    RETURN {
        'email': e,
        'user': NEIGHBORS(email, userEmail, e, 'inbound', [], {includeData:true})
    }

Other solution

I have also used this solution, with the same result

FOR e IN email
    FILTER e.address == @email
    LET u = (NEIGHBORS(email, userEmail, e, 'inbound', [], {includeData:true}))
    RETURN u

Another solution

Another solution I came up is

FOR e in email
    FILTER e.address == @email
    FOR p IN TRAVERSAL(user, userEmail, e._id, "inbound", {paths: true})
    RETURN p

This returns the vertices and edges, but only correctly in the second set of results. I could hard code in to use the second set of returned values, but I don't think that is the best way of doing so.

Is the current solution the best or is there a better way of doing what I want?

1

There are 1 best solutions below

2
On BEST ANSWER

You should use the ArangoDB 2.8 new style pattern matching traversals to start with. Lets adopt the query with the geoindex for this:

FOR oneEmail IN email
  FILTER oneEmail.address == @email
  FOR v, e IN 1..1 INBOUND oneEmail userEmail
    FILTER e.primary == true
    RETURN {
      'email': oneEmail.address,
      'user': v
    }

To add the filter on primary in old style NEIGHBORS queries that you used in your question use the edgeExamples parameter:

FOR e IN email
  FILTER e.address == @email
  RETURN {
    'email': e,
    'user': NEIGHBORS(email, userEmail, e, 'inbound',
                      [{ Primary : true }],
                      {includeData:true})
  }

In general if emails can always belong to only one user (1:n relation), I'd question whether your choice for graphs is the preferable way in first place, and joins without an edge collection would be a better choice.