How to combine multiple conditions with cypher

To determine which nodes are connected to specific multiple nodes
I created a Cypher like below

MATCH
(a:Label1{name:"test1"})--(b:Target),
(a:Label1{name:"test2"})--(b:Target)
RETURN a

If these conditions increase, it will become very complicated, but is there a description that summarizes it?

for example:

WITH["test1","test2] AS list1
MATCH p = (a:Label1)--(b:Target)
WHERE all(x IN nodes(p) WHERE a.name list1)
RETURN p

Just a note, your first query should not work, as you are reusing the variables 'a' and 'b' in your second match. When you match something like below, where I reused 'a', it is going to find the first node based on the first match and assigned bind it to variable 'a'. In the next line it is asking to find a node bound to variable 'a' (since it already exists) and has label "Label1" and name property "test2". The end result will be no match since the node bound to variable 'a' has a name property equal to 'test1'.

MATCH
(a:Label1{name:"test1"})
(a:Label1{name:"test2"})
RETURN a

Here is an example shown with labels. Here I create three nodes, one with label X, another with label Y, and another with both labels X and Y.

create(:X{id:0}),(:Y{id:1}),(:X:Y{id:2})

You see when I run the following query, the result if the node with both labels X and Y. That is because in the first match it found the node with label X and the node with labels X and Y. These nodes where bound to the variable 'n'. In the next match it looked for the nodes bound to 'n' that had a label 'Y'. The result is just the node with both labels.

Screen Shot 2024-01-30 at 8.46.19 AM

Screen Shot 2024-01-30 at 8.43.02 AM

In summary, when you reuse a bound variable, any new conditions are a refinement on the already found entity.

To correct the first query you need to assign each 'Label' entity to separate variables.

create(a1:Label1{name:"test1"}),(a2:Label1{name:"test2"})
create (a1)-[:HAS_TARGET]->(b:Target{id:1})
create (a2)-[:HAS_TARGET]->(b)

In your second query you are using the "all" list predicate on the list "nodes(p)". This is not necessary. Keep in mind that each pattern that match will return a row. As such, your match will produce a row for the "test1" node and a row for the "test2" node. These will be different values of 'p'. The function "node(p)" will return all the nodes along the path 'p'. This means nodes 'a' and 'b' for each of the two matches. Here is how I would refactor it.

with["test1","test2"] as list1
match p = (a:Label1)--(b:Target)
where a.name in list1
return p

What is happening here is that the match is producing rows for every Label1 node that exists in the db that is also related a Target. It then filters row-by-row to pass only the rows that have an 'a' node with a name property in the list. Keep in mind this query is not finding Label1 nodes that are related to the same Target node, as you had in your first query.

1 Like

thank you for reply,glilienfield
I was in a hurry and the first query was wrong.
The query I really wanted to write is below.

MATCH
(a{name:"test1"})--(b),
(a{name:"test2"})--(b)
RETURN b

I wanted to extract the data connected to both test1 and test2 nodes.
So the final query is OR(IN), which is not what you want.I'm very sorry

No worries. Glad you figured it out.