arangodbarangodb-php

Traverse up in ArangoDB


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?


Solution

  • 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.