tgig
tgig

Reputation: 153

ArangoDB AQL FILTER graph for matching edge attributes

I have one words collection and one word_relations edge collection. Words have relationships to other words, like synonym, hasPart, partOf, hasType, typeOf, etc.

I am trying to figure out how to FILTER an AQL graph query so that all paths are followed, but paths with more than one edge contain identical edge attribute of relation_type.

E.g., I want this result (all returned paths, whether one or many, contain a single relation_type attribute value):

[
  {
    "edges": [
      {
        "_from": "library/parent",
        "_to": "library/organism",
        "relation_type": "typeOf"
      }
    ],
    "vertices": [
      {
        "_key": "parent",
        "word": "parent"
      },
      {
        "_key": "organism",
        "word": "organism"
      }
    ]
  },
  {
    "edges": [
      {
        "_from": "library/parent",
        "_to": "library/organism",
        "relation_type": "typeOf"
      },
      {
        "_from": "library/organism",
        "_to": "library/scheme",
        "relation_type": "typeOf"
      }
    ],
    "vertices": [
      {
        "_key": "parent",
        "word": "parent"
      },
      {
        "_key": "organism",
        "word": "organism"
      },
      {
        "_key": "scheme",
        "word": "scheme"
      }
    ]
  },
  {
    "edges": [
      {
        "_from": "library/parent",
        "_to": "library/stepparent",
        "relation_type": "hasType"
      },
      {
        "_from": "library/stepparent",
        "_to": "library/stepmother",
        "relation_type": "hasType"
      }
    ],
    "vertices": [
      {
        "_key": "parent",
        "word": "parent"
      },
      {
        "_key": "stepparent",
        "word": "stepparent"
      },
      {
        "_key": "stepmother",
        "word": "stepmother"
      }
    ]
  }
]

NOT this result (the relation_type attribute value changes within one path):

[
  {
    "edges": [
      {
        "_from": "library/parent",
        "_to": "library/organism",
        "relation_type": "typeOf"
      }
    ],
    "vertices": [
      {
        "_key": "parent",
        "word": "parent"
      },
      {
        "_key": "organism",
        "word": "organism"
      }
    ]
  },
  {
    "edges": [
      {
        "_from": "library/parent",
        "_to": "library/organism",
        "relation_type": "typeOf"
      },
      {
        "_from": "library/organism",
        "_to": "library/zygote",
        "relation_type": "hasCategories"
      }
    ],
    "vertices": [
      {
        "_key": "parent",
        "word": "parent"
      },
      {
        "_key": "organism",
        "word": "organism"
      },
      {
        "_key": "zygote",
        "word": "zygote"
      }
    ]
  },
  {
    "edges": [
      {
        "_from": "library/parent",
        "_to": "library/family_unit",
        "relation_type": "memberOf"
      },
      {
        "_from": "library/family_unit",
        "_to": "library/sibling",
        "relation_type": "hasMembers"
      }
    ],
    "vertices": [
      {
        "_key": "parent",
        "word": "parent"
      },
      {
        "_key": "family_unit",
        "word": "family unit"
      },
      {
        "_key": "sibling",
        "word": "sibling"
      }
    ]
  },
]

There are many different kinds of relation_type attribute values. I do not want to filter to a specific value, I don't care what the initial value is, I just want all follow-on attribute values to be the same as the first.

The AQL to get the second (undesirable) result looks like:

FOR v, e, p IN 1..2 OUTBOUND 'words/parent' word_relations
  RETURN p

I have tried a few different filters, none of which work:

0 results:

FOR v, e, p IN 1..2 OUTBOUND 'library/parent' library_relations
  FILTER p.edges[*].relation_type ALL == p.edges[*].relation_type
  RETURN p

Only returns 2 paths, b/c the FILTER requires the second to exist:

FOR v, e, p IN 1..2 OUTBOUND 'library/parent' library_relations
  FILTER p.edges[0].relation_type == p.edges[1].relation_type
  RETURN p

Thanks for your help!

Upvotes: 2

Views: 488

Answers (1)

peak
peak

Reputation: 116690

The following could be used for larger values of MAX as well:

FOR v, e, p IN 1..2 OUTBOUND 'library/parent' library_relations
  FILTER p.edges[*].relation_type ALL == e.relation_type
  RETURN p

Unfortunately, the AQL optimizer is tragically impaired at the moment (see https://github.com/arangodb/arangodb/issues/3979#issuecomment-350686061), so most likely you would have to work around its limitation, e.g. by prepending the above with:

FOR tmpV, tmpE  IN 1..1 OUTBOUND 'library/parent’ library_relations

and then using tmpE.relation_type instead of e.relation_type.

Upvotes: 3

Related Questions