drgraduss
drgraduss

Reputation: 381

Neo4j/Cypher matching first n nodes in the traversal branch

I have graph: (:Sector)<-[:BELONGS_TO]-(:Company)-[:PRODUCE]->(:Product).

I'm looking for the query below.

Start with (:Sector). Then match first 50 companies in that sector and for each company match first 10 products.

First limit is simple. But what about limiting products.

Is it possible with cypher?

UPDATE

As @cybersam suggested below query will return valid results

MATCH (s:Sector)<-[:BELONGS_TO]-(c:Company)
WITH c
LIMIT 50
MATCH (c)-[:PRODUCE]->(p:Product)
WITH c, (COLLECT(p))[0..10] AS products
RETURN c, products

However this solution doesn't scale as it still traverses all products per company. Slice applied after each company products collected. As number of products grows query performance will degrade.

Upvotes: 0

Views: 450

Answers (2)

InverseFalcon
InverseFalcon

Reputation: 30407

Updating with some solutions using APOC Procedures.

This Neo4j knowledge base article on limiting results per row describes a few different ways to do this.

One way is to use apoc.cypher.run() to execute a limited subquery per row. Applied to the query in question, this would work:

MATCH (s:Sector)<-[:BELONGS_TO]-(c:Company)
WITH c
LIMIT 50
CALL apoc.cypher.run('MATCH (c)-[:PRODUCE]->(p:Product) WITH p LIMIT 10 RETURN collect(p) as products', {c:c}) YIELD value
RETURN c, value.products AS products

The other alternative mentioned is using APOC path expander procedures, providing the label on a termination filter and a limit:

MATCH (s:Sector)<-[:BELONGS_TO]-(c:Company)
WITH c
LIMIT 50
CALL apoc.path.subgraphNodes(c, {maxLevel:1, relationshipFilter:'PRODUCE>', labelFilter:'/Product', limit:10}) YIELD node
RETURN c, collect(node) AS products

Upvotes: 1

cybersam
cybersam

Reputation: 67009

Each returned row of this query will contain: a sector, one of its companies (at most 50 per sector), and a collection of up to 10 products for that company:

MATCH (s:Sector)<-[:BELONGS_TO]-(c:Company)
WITH s, (COLLECT(c))[0..50] AS companies
UNWIND companies AS company
MATCH (company)-[:PRODUCE]->(p:Product)
WITH s, company, (COLLECT(p))[0..10] AS products;

Upvotes: 1

Related Questions