wener
wener

Reputation: 7750

In ArangoDB how to select a node in graph filter by multi edge?

Data like this

a->b,c,d
b->c,d
d->a,b

Query like this

FOR n in Nodes
FOR v,e,p IN 1 ANY n GRAPH 'MyGraph'
// Only need a
// HOW TO WRITE: FILTER n have an edge to `b` and n have an edge to `d`

// This will select a,b,c
FILTER v._key in [ 'b', 'd' ]
RETURN p

I want to select a node with edge to b and d, not b or d, but how ?

EDIT

Data

insert {_key:'a'} in nodes
insert {_key:'b'} in nodes
insert {_key:'c'} in nodes
insert {_key:'d'} in nodes

insert {_from:'nodes/a',_to:'nodes/b'} into relate
insert {_from:'nodes/a',_to:'nodes/c'} into relate
insert {_from:'nodes/a',_to:'nodes/d'} into relate
insert {_from:'nodes/b',_to:'nodes/c'} into relate
insert {_from:'nodes/b',_to:'nodes/d'} into relate
insert {_from:'nodes/c',_to:'nodes/d'} into relate

A very dummy solution is

for n in nodes
for v,e,p in 1 OUTBOUND n graph 'MyGraph'
filter v._key == 'b'
for v2,e2,p2 in 1 INBOUND v graph 'MyGraph'
sort v2._key == 'd'
return v2

But this query only work for two conditions,if I need one more condition I have to write one more for query.

Upvotes: 0

Views: 180

Answers (1)

mpv89
mpv89

Reputation: 1891

I see several queries you could use. I added an vertex e to show how they look when you have more conditions.

I. the most performant query should be:

FOR v IN 1 INBOUND 'nodes/b' graph 'MyGraph'
  FILTER length(FOR d IN 1 OUTBOUND v graph 'MyGraph'
    FILTER d._key == 'd'
    LIMIT 1
    RETURN 1) == 1
  FILTER length(FOR e IN 1 OUTBOUND v graph 'MyGraph'
    FILTER e._key == 'e'
    LIMIT 1
    RETURN 1) == 1
  RETURN v

The query searchs for neighbors of b and filters over a sub-query with the founded neighbors and checks whether they are connected with d and e.

II. a more transparent but also slower query:

LET b = (FOR v IN 1 INBOUND "nodes/b" graph 'MyGraph' RETURN v)
LET d = (FOR v IN 1 INBOUND "nodes/d" graph 'MyGraph' RETURN v)
LET e = (FOR v IN 1 INBOUND "nodes/e" graph 'MyGraph' RETURN v)
RETURN INTERSECTION(b, d, e)

The query makes a sub-query for every searched node and returns the intersection of their neighbors.

III. a very generic query with use of bindVars, but also the slowest:

bind parameters:

{
    "targets": ["b","d","e"]
}

query:

FOR n IN nodes
  LET neighbors = (FOR v,e,p IN 1 OUTBOUND n graph 'MyGraph'
    FILTER v._key IN @targets
    RETURN v._key)
FILTER @targets ALL IN neighbors
RETURN n

Yes, it is the slowest but you have never to change the query itself any more when you want to add more conditions. You only have to change the bind parameters.

Upvotes: 1

Related Questions