简体   繁体   中英

ArangoDB graph traversal with different filter for different vertex types

I need to be able to filter arangodb graph traversal by vertex type. There are two vertex types, let's say vA and vB. There is only one type of edge, which can connect _to and _from either type of vertex.

vA has an attribute 'pfi' with numeric value. vB has an attribute 'aliases', which is a dictionary (document) of a few attribute/value pairs integer-as-string): integer. The integer-as-string attribute contain the same sort of data/numbers as the pfi attribute in vA.

I start with each starting vertex p0 (determined earlier in the query). Each p0 has attributes "zero point id" and "pfi".

I need to traverse in the outbound direction, and only keep the paths where all vertices of type vA have 'pfi' that matches the p0.pfi, and all vertices of type vB have an 'alias' attribute that matches the pfi.

FOR p0 in points
    FOR v, e, p IN 1..5 OUTBOUND p0['zero point id'] GRAPH 'grph'
        FILTER p.vertices[*]['pfi'] ALL == p0['pfi']
            OR p.vertices[*]['aliases'][TO_STRING(p0['pfi'])] NONE == null
        RETURN {
            'pfi': p0['pfi']
            , 'vertices': p.vertices
            , 'edges': p.edges
        }

I've tried several syntax variations on the above, all with the same behaviour: I get all (unfiltered) paths if I remove the filter, and an empty result with the filter. I think it's because all paths contain both vertex types, and the logic of the OR does not mean that either condition can be true for any single vertex to pass.

How to I phrase this so that the first condition applies to vA types, and the second to vB types?

I found this: Filter on different graph edge types using ArangoDb AQL , which can be adapted to

FOR p0 in points
    FOR v, e, p IN 1..5 OUTBOUND p0['zero point id'] GRAPH 'grph'
        LET counter = (
            FOR v2 in p.vertices
                FILTER v2['pfi'] == p0['pfi']
                    OR HAS(v2['aliases'], TO_STRING(p0['pfi']))
            RETURN v2
        )
        FILTER COUNT(counter) == COUNT(p.vertices)
RETURN {
    'pfi': p0['pfi']
    , 'edges': p.edges
}

It works, but it feels like a clumsy workaround. Is there a more elegant way?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM