How to match a subset of nodes, then match a pattern within the subset?

(Benmathiesen) #1

Hi everyone,

I'm new to cypher and I'm trying to run a query on a large graph.

The idea is to match a variable length pattern, but only within a subset of nodes from the full graph. The graph represents all the parts used to construct a set of products, with the components of each product indicated by the 'uses' relation and the hierarchy of construction for a single product indicated by the 'has' relation.

So I wrote this:

MATCH (m:Product {serialnumber:'8352'})-[:uses]->(p:Part)
WITH m,p
MATCH path=(p)<-[r:has]-(nha:Part)<-[:has*]-(anc:Part)
RETURN path
LIMIT 100

But the results look like the second MATCH is finding parent nodes from the whole graph, not only the subset p defined by the first MATCH. I was hoping that the first MATCH could define a subgraph that only includes nodes from a single product.

How can I ensure that the paths returned by the query only inlcude nodes that satisfy the first MATCH?

Many thanks,
Ben

0 Likes

(Elaine Rosenberg) #2

Hi Ben,

The :has* relationship tells the graph engine to get any part that is related to any other part, no matter how many hops away. If all of the parts in the database are ultimately connected, I would see where it would return all of the parts.

Did you try a query such as:

MATCH (p1:Product {serialnumber:'8352'})-[:uses]->(p2:Part)<-[:has*1..3]-(p3:Part)
return p1, p2, p3

just to see what depth the Parts are related (for example 3 hops away)

Elaine

0 Likes

(Benmathiesen) #3

Hi Elaine,
Thanks for responding. Since I posted, I managed to get the results I wanted with the following query, which gets me all the paths from ancestor parts to child parts at various depths.
I'm obliged to use variable paths and to plumb the depths of the tree.
However, I'm not sure that the way I'm searching the subtree associated with this single product is the most efficient. If you have any advice on optimizing, I'm all ears! The subtree of parts used by this product still has ~100k nodes, and some products can have ~1 million individual parts.
Best,
Ben

MATCH (m:Product {serialnumber:'8352-DD'})-[:uses]->(p:Part)
WITH m, collect(p) AS mparts
MATCH path=(anc:Part)-[:has*]->(child:Part)
WHERE ALL(node IN nodes(path) WHERE node IN mparts)
WITH m, child, anc, path, relationships(path)[-1] AS rnha, nodes(path)[-2] as nha
RETURN stuff I want

0 Likes