Runtime and result issues executing star-shaped pattern

Hey everyone,

I am having some problems executing pattern matching on star-shaped graphs as follows:

Suppose we have a set of nodes, which are arranged like a chessboard, connected with relations (right, bottom) to their direct neighbors (in example a 4x4 board). A pattern matching for finding any 3x3 boards is executed without any problems. For each of these matches, I have created a special node ("MatchNode") with a UUID, which has relations to all nodes of one match, such we have a star-shaped structure here.

My goal was now to use the MatchNode with its UUID to validate, if the connected 3x3 board has still a valid structure or not. But running the Cypher query starting with the MatchNode and then followed by the rest of the nodes and relations is extremely slow (5-10 seconds). Furthermore, sometimes it finds no matching, while it is definitely there. Running the "Profile" mode showed, that there are many Joins, but I have no idea why, or how I could solve this.

Do you have any idea why is that or how I could improve my cypher query?

Here is my Cypher Query:

MATCH  
	(matchingNode:Match {uuid: "c3e0df35-26d8-4d9b-8505-4276d60931d2"})
WITH 	matchingNode
MATCH
	(matchingNode)-[:matches_b]->(b:Board), 
	(matchingNode)-[:matches_field11]->(field11:Field), (matchingNode)-[:matches_field12]->(field12:Field), (matchingNode)-[:matches_field13]->(field13:Field), 
	(matchingNode)-[:matches_field21]->(field21:Field), (matchingNode)-[:matches_field22]->(field22:Field), (matchingNode)-[:matches_field23]->(field23:Field), 
	(matchingNode)-[:matches_field31]->(field31:Field), (matchingNode)-[:matches_field32]->(field32:Field), (matchingNode)-[:matches_field33]->(field33:Field)
WITH
	matchingNode, b, field11, field12, field13, field21, field22, field23, field31, field32, field33
MATCH	(b)-[:fields]->(field11), (b)-[:fields]->(field12), (b)-[:fields]->(field13),
	(b)-[:fields]->(field21), (b)-[:fields]->(field22), (b)-[:fields]->(field23),
	(b)-[:fields]->(field31), (b)-[:fields]->(field32), (b)-[:fields]->(field33),
	(field11)-[:right]->(field12), (field11)-[:bottom]->(field21),
	(field12)-[:right]->(field13), (field12)-[:bottom]->(field22),
	(field13)-[:bottom]->(field23),  
	(field21)-[:right]->(field22), (field21)-[:bottom]->(field31), 
	(field22)-[:right]->(field23), (field22)-[:bottom]->(field32), 
	(field23)-[:bottom]->(field33), 
	(field31)-[:right]->(field32), 
	(field32)-[:right]->(field33)
RETURN matchingNode.uuid as uuid

Welcome Jannik,

It is not completely clear to me what your use case is but I would make sure that there is a unique constraint on Match(uuid). And I would write the query in one pattern like this:

MATCH (matchingNode:Match {uuid: "c3e0df35-26d8-4d9b-8505-4276d60931d2"})
WITH 	matchingNode
MATCH	(matchingNode)-[:matches_b]->(b:Board)
, (matchingNode)-[:matches_field11]->(field11:Field)<-[:fields]-(b)
, (matchingNode)-[:matches_field12]->(field12:Field)<-[:fields]-(b)
, (matchingNode)-[:matches_field13]->(field13:Field)<-[:fields]-(b)
, (matchingNode)-[:matches_field21]->(field21:Field)<-[:fields]-(b)
, (matchingNode)-[:matches_field22]->(field22:Field)<-[:fields]-(b)
, (matchingNode)-[:matches_field23]->(field23:Field)<-[:fields]-(b)
, (matchingNode)-[:matches_field31]->(field31:Field)<-[:fields]-(b)
, (matchingNode)-[:matches_field32]->(field32:Field)<-[:fields]-(b)
, (matchingNode)-[:matches_field33]->(field33:Field)<-[:fields]-(b)
, (field11)-[:right]->(field12)
, (field11)-[:bottom]->(field21)
, (field12)-[:right]->(field13)
, (field12)-[:bottom]->(field22)
, (field13)-[:bottom]->(field23)
, (field21)-[:right]->(field22)
, (field21)-[:bottom]->(field31)
, (field22)-[:right]->(field23)
, (field22)-[:bottom]->(field32)
, (field23)-[:bottom]->(field33)
, (field31)-[:right]->(field32)
, (field32)-[:right]->(field33)
RETURN matchingNode.uuid as uuid

Did you use profile/explain on this query?

regards
Kees

Hi Kees,
many thanks for your answer.
We use the Neo4j database for storing MDE models. Our goal was to validate a Matching after executing some graph transformations, but much faster than running a complete new Matching on the whole database. Therefore we want to use the MatchingNode pointing to the nodes of a Match.

Using the unique constraint does not make much difference. We had used an index on the MatchingNode UUID before. The executing-plan of your query was pretty much the same. The first execution needs around 6s, any further around 20ms. But why does it take so long first? Our model is very small.

In addition, our main problem is, sometimes the Neo4j finds a valid match, but sometimes it does not find a valid match using the same query. :face_with_raised_eyebrow:

Best regards,
Jannik