Cypher: match all couples of nodes iff they share a specific relationship


I build a very simple graph having different type of nodes and just one type of relationship, named MAPPING1TO1; so, each couple of nodes share the same type of relationship. This relationship (named EventTag) has just one property: an array. In particular, the array might have just one of the following forms:

[1] (a_1,b_1), ..., (a_n, b_n)
[2] c_1, c_2, ..., c_m

where a_i, b_i and c_i can be any integer number.

I would write a query in Cypher that returns all the couples of nodes sharing a relationship that satisfy the following condition: there exists inside the array EventTag an element equal to x, given in input.

I have written the following query to solve this problem:

WITH "912" AS event
MATCH (a)-[r]->(b)
WHERE SINGLE(item in r.EventoTag WHERE SUBSTRING(item,0,4) CONTAINS event)

The SUBSTRING part is the way to check if there is the item of interest inside the array.

Anyways, I don't understand why this query dosen't solve the problem; the result is the following:

The relationships that I haven't highlighted are good, i.e. it's right they are part of the result, but the highlighted relationship dosen't, why it's taken in the result? If you look the EventTag properties, you can see there isn't an item containing the substring 912, the item I'm looking for.

Do you have any idea? Thank you very much.

So you're trying to match the array that's inside the relationship as a property?
Then you're probably going to want to do something like this:

MATCH (n1:Node1)-[r:MAPPTING1TO1]->(n2:Node2)
WHERE r.EventToTag[array index you want to check] = "912" 
return return n1, n2

This should return the pair of nodes joined by the relationship that contains the number you're after.

Thank you for the reply!

It's right, but I don't know if the array contains this parameter, and where is it. So I should search inside it.

I would return both the nodes and also the relation between them that satisfy the condition.

If you don't know the index you should be able to just use:

WHERE "912" in r.EventToTag

and return what you're after

Thank you for the reply!

The only problem is the array dosen't contain extact matches of this item. For example, the i-th index of the EventoTag array might contains "(912, 31)", so i should check if "912" is a substring of some element inside the array.

The functions you're looking for are in here Predicate functions - Cypher Manual probably the Any() method.

Yes, exactly! This is the query I've wrote to solve the problem:

WITH "912" AS event
MATCH p=(a)-[r]->(b)
WHERE ANY(item in r.EventoTag WHERE SUBSTRING(item,0,4) CONTAINS event)

But, still, the result is wrong! Inside the result there are not correct edges, and I don't understand why; For example, if you look the image inside the first post, the highlighted edge dosen't contain the string "912" in its substrings, but still the edge is taken.

I don't have a ton of time right this second. I'll look at it some more and get back to you.

Sure, thank you very much again!

I'm sorry to bother you Muddy, do you have any news about it? I have tried also with SINGLE, but still the result is not right. Really do not understand why the query returns the edges that does not satisfy the condition

Maybe like @michael.hunger showed me, we need to include the relationship in the query, like:

WITH "2019-01-01" as endDate
MATCH (a:Abstract {name: Name})
WHERE ALL( w IN [(w)-[:ON]->(a) | w] WHERE w.lastProdDate > endDate)

in your case that might look like

WITH "912" AS event
MATCH (n1:NODE1)-[r:MAPPING1TO1]->(n1:Node2)
WHERE ALL ( r IN [(n1)-[r:MAPPING1TO1]->(n2) | r] WHERE r.eventToTag CONTAINS event)
RETURN n1, n2

That should explicitly return the relationships that contain the event. Additionally, while it doesn't fit your currently data model, you might consider just adding event nodes between the two other nodes n1 and n2. That would allow you to search a bit more precisely as well as add indexes on the event nodes, which you can't add to relationships and possibly speed your query up a bit.

Thank you for the reply!

I understood the query but the problem is that I still need to iterate through the EventoTag properties and check if exists an item that contains the SUBSTRING(0,4,event). I don't know how to integrate this control inside your query.

There is the answer:

1 Like