How to check OR operator between two or more relationships

hi
i want to check existence of a node with some relationships that if one of them exist the node must be selected as result.

:X means anythings
match (a:A)-[:X]->(b:B)-[:X]->(c:C),
(b)-[:X]->(d:D),
(b)-[:X]->(e:E)
return a,b

this means select all of (a:A)-[:X]-(b:B) (s) that b has at least one c AND one d AND one e
how can i change this behavior into :
Select all of (a:A)-[:X]-(b:B) which b has
1- one c:C
OR
2- one d:D
OR
3- one e:E

thanks a lot

MATCH (a:A)-[:X]-(b:B)
OPTIONAL MATCH (b:B)-[:X]->(c:C), (b)-[:X]->(d:D), (b)-[:X]->(e:E)
RETURN c, d, e

Check out this link: https://neo4j.com/docs/cypher-manual/current/clauses/optional-match/
Hope this helps you.

hi,
I guess i didn't explain my question well.
I want to select those nodes (in this example B) that at least has one of (C) OR (B) OR (D) ,not those (B)s that hasn't any of them.
optional match tell to me :
you can select all of (B) regardless of related Node after that in cypher in this situation (C), (D), (E)
this means i can select
those (B)s that has no (C) or (D) or (E)
those (B)s that has only (C)
those (B)s that has only (D)
those (B)s that has only (E)
those (B)s that has (C) and (D)
those (B)s that has (C) and (E)
those (B)s that has (D) and (E)
and those (B)s that has (C) and (D) and (E)
i find one solution for this but that is verbose.
//step 1 : create list of (B)s that has (C) named as list1
MATCH (a:A)-[:X]->(b:B)-[:X]->(c:C)
with collect(b) as list1
//step2: create list of (B)s that has (D) named as list2
MATCH (a:A)-[:X]->(b:B)-[:X]->(d:D)
with list1, collect(b) as list2
//step 3: create list of (B)s that has (E) named as list3
MATCH (a:A)-[:X]->(b:B)-[:X]->(d:D)
with list1, list2, collect(b) as list3
//step 4 : match those (B)s that exist at least in one of list1 or list2 or list3
MATCH (a:A)-[:X]->(b:B)
where any( item in list1 where item=b) or any( item in list2 where item=b) or any(item in list3 where item=b)
return a,b
i know this is correct, but i don't know this is efficient
thanks to any one that help.

@bozorgi

Welcome to the group.
You can try this
match (a:A)-[:X]->(b:B)-[:X]->(c:C)
return a,b
Union
match (a:A)-[:X]->(b:B)-[:X]->(d:D)
return a,b
Union
match (a:A)-[:X]->(b:B)-[:X]->(e:E)
return a,b

Thank Vivek for your reply
This is correct.
But if I want to do it without any Union how can I do it.
suppose this pattern
(A)-->(B)-->(C)
(C)-->(M)
(C)-->(N)
(B)-->(D)
(B)-->(E)-->(F)
(E)-->(G)
In B, C and E ( branch points) between outgoing relationships OR operator exists.
As a general approach how can do this in one cypher with one return statement.

MATCH (a:A)-[:X]->(b:B), (c:C), (d:D), (e:E)
where ((b:B)-[:X]->(c:C) OR (b:B)-[:X]->(d:D) OR (b:B)-[:X]->(e:E))
RETURN a,b
1 Like

Not sure if I completely understood your requirement.
However to generalize A->B->* try below
Match path= (a:A)-[]->(b:B)-[]-> ()
return path

If you want to specify the relationship name then better

Thank jaini. Kiran
I have to test this. If this works, my problem will be solved.

1 Like

thanks for your reply

i am working on some patterns, some of them are as simple as linear pattern such as

  • (A)-[R]->(B)-[R]->(C)
    some of them are a little more complicated
  • (A)-[R]->(B)-[R]->(C)
  •               (B)-[R]->(D)
    

in these cases one or more Branch Point exist in patterns. Nodes like B are Branch Point. which means in this point pattern forked into more than one line of pattern.
(B) = branch point
1- (B)-[R]->(C)
2- (B)-[R]->(D)
...
these (BP)s may be chained together. Some of these (BP)s have special conditions, and some haven't.
for example
1- B must be related to C by R
and
2- B must be related to D by R

  • as in Neo4j Cypher documents explained, these conditions must be written with WHERE clause after respective MATCH clause. so we have

  • MATCH ((a:A)-[:R]->(b:B)),

  •                             ((b)-[:R]->(:C)),
    
  •                             ((b)-[:R]->(:D))
    

return a,b

  • if operator of this (BP) changes to OR as [jaini.kiran] explained the cypher changes as follows

MATCH (a:A)-[:R]->(b:B)
where (b)-[:R]->(:C) OR (b)-[:R]->(:D)
return a,b
or as you explained this case can be implemented with UNION clause

  • if these (BP)s are repeated

  • (A)-[R]->(B)

  •           (B)-[R]->(C)
    
  •                         (C)-[R]->(M)
    
  •                         (C)-[R]->(N)
    
  •          (B)-[R]->(D)
    
  •                        (D)-[R]->(P)
    
  •                        (D)-[R]->(Q)
    

cypher statement changes to :
MATCH (a:A)-[R]->(b:B)
WHERE exists((b)-[:R]->(:C) **1) or exists((b)-[:R]->(:D) **2)
RETURN a,b

Suppose all (BP)s have OR operator between outgoing relationships.

Question : in **1 and **2 how can i write the continuation of the cypher.

i counted on the (BP)s and their leaves.
(BP)s B,C and D
Leaves M,N,P and Q
based on leaves for each BP create a list of valid (BP)s. from last to first

** C Break Point
1-MATCH (A)-[R]->(B)-[R]->(C)-[R]->(M)
with collect(C) as c_list1
2-MATCH (A)-[R]->(B)-[R]->(C)-[R]->(N)
with c_list1, collect(C) as c_list2
3-MATCH (A)-[R]->(B)-[R]->(c:C)
where any(item in c_list1 where item=c) or any(item in c_list2 where item=c)
with collect(c) as c_list

** D Break Point
4-MATCH (A)-[R]->(B)-[R]->(D)-[R]->(P)
with c_list, collect(D) as d_list1
5-MATCH (A)-[R]->(B)-[R]->(D)-[R]->(Q)
with c_list, collect(D) as d_list2
6-MATCH (A)-[R]->(B)-[R]->(d:D)
where any(item in d_list1 where item=d) or any(item in d_list2 where item=d)
with c_list, collect(d) as d_list

** B Break Point
7-MATCH (A)-[R]-(B)-[R]-(c:C)
where any( item in c_list where item=c)
with d_list, collect(B) as b_list1
8-MATCH (A)-[R]-(B)-[R]-(d:D)
where any( item in d_list where item=d)
with b_list1, collect(B) as b_list2

** Create Result
9-MATCH (a:A)-[R]->(b:B)
where any(item in b_list1 where item=b) or any(item in b_list2 where item=b)
return a,b

? is this the right solution

thanks a lot

@bozorgi,

If I see at high level you are trying to implement tree.
If you provide small sample dataset and usecase then it will be useful for us to help you out.

hi
I am working on translating abstract queries into neo4j queries.
The user defines an abstract query based on a set of predefined concepts.
In this task, the major challenge is to manages points ( Query Node not Graph Node ) where different conditions defined on a node. these challenges are aggregate functions ( count, exists, not-exists ) and combining conditions with OR.
I am currently working on solving these challenges so that an unlimited number of these points can be managed within one command ( cypher statement with only one RETURN clause )
this is very similar to nested queries in relational databases. some inner queries provide source for outer queries - reverse approach.
In the previous post I defined a pattern that results the tree without deducing the relationships outside the pattern. But if the inference settings are made, the result is graph.
(A)-[R]->(B)
-----------(B)-[R]->(C)
-----------------------(C)-[R]->(M)
-----------------------(C)-[R]->(N)
-----------(B)-[R]->(D)
-----------------------(D)-[R]->(P)
-----------------------(D)-[R]->(Q)

Is the cypher in the previous post correct?
I apologize in advance for my poor English.

@bozorgi
I clearly understood your project. You are trying to create a wrapper framework on Cypher that is rather user friendly so that one can query Neo4j DB using that wrapper rather than Cypher. The wrapper framework will call Cypher.
To implement that framework your are trying to ingest cypher statements in tree and now you want to traverse the tree.
You can try the solutions given in last post by me of @jaini.kiran.
However I would say that if my understanding is correct, Nodes A,B,C,D,E,.. belong to one Label rather than they distinct Lables.
Traversing the tree can we using with recursive loop please look into the solution provided by @ Andrew in Determine number of node relationships in recursive query

Thank for your time.