lug
lug

Reputation: 23

I need help for a query with Neo4j

Here is a simplified schema of my Neo4j DB model. I tried several Cypher queries based on some posts, but nothing work.

My Neo4j Model Example

I would like to find all the components and all the suppliers, for a bike number.

The complexity is that some components are linked to suppliers and in that cases, the branch is followed only if the upper component has the right version.

Examples:

I would like to get the nodes and the relationships.

Can someone help me ?

Upvotes: 0

Views: 174

Answers (3)

Tezra
Tezra

Reputation: 8833

Basically, what you want is to pull all sub-graph items but filtering out relations paths that fail a filter. You can use ALL/NONE/ANY to make sure the picked up paths don't violate any constraints.

Here is an example that assumes that from and to can be defined independently, but I think it is clear enough to adjust to your needs as you like. (Note: You can use TYPE(r) to check the relation type name too)

WITH 11 as num
MATCH p=(s:Bike)-[*..25]-(n) 
WHERE 
ALL(r IN RELATIONSHIPS(p) WHERE 
    (NOT EXISTS(r.RANGEFROM) OR toInteger(r.RANGEFROM) <= num) AND 
    (NOT EXISTS(r.RANGETO) OR num <= toInteger(r.RANGETO)))
AND TYPE(RELATIONSHIPS(p)[-1]) = "LO"
WITH NODES(p) as ns, RELATIONSHIPS(p) as rs
UNWIND ns as n UNWIND rs as r
RETURN COLLECT(DISTINCT n), COLLECT(DISTINCT r)

Or this should be more efficient.

WITH 11 as num
MATCH (ci)-[lo:LO]->(ds)
WHERE toInteger(lo.RANGEFROM) <= num <= toInteger(lo.RANGETO)
WITH ds, COLLECT(lo) as lo
MATCH p=shortestpath((b:Bike)-[*..25]->(ds))
WHERE ALL(r IN RELATIONSHIPS(p) WHERE TYPE(r) <> "LO" OR r in lo)
WITH NODES(p) as ns, RELATIONSHIPS(p) as rs
UNWIND ns as n UNWIND rs as r
RETURN COLLECT(DISTINCT n), COLLECT(DISTINCT r)

Note: If you need better performance, you might want to look into using the Neo4J Traversal API.

Upvotes: 0

Tom Geudens
Tom Geudens

Reputation: 2656

Not sure if I understand correctly, but would this work ?

MATCH p=(b:Bike {bnumber = 6})-[hc:HAS_COMPONENT]-(c:Component)-[hs:HAS_SUPPLIER]-(s:Supplier)
WHERE hs.frombike >= bnumber 
  AND hs.tobike <= bnumber
RETURN p;

I agree with @cybersam that you could do with a simplification of the model. Do raise that concern.

Hope this helps.

Regards, Tom

Upvotes: 1

cybersam
cybersam

Reputation: 66947

Here is a simple data model. In addition to the Bike, Component, and Supplier node labels, this model adds a Part node label.

(b:Bike)-[HAS_COMPONENT]->(c:Component)-[:IS_PART]->(p:Part)
(c)-[:SUPPLIED_BY]->(s:Supplier)

In this model:

  • A Part is a specific item made by a specific manufacturer, and it can be sold by any number of Suppliers.
  • A Bike is made up of multiple Components, each of which is a Part that was purchased from a specific Supplier.

With this model, here is a sample query to return, for a specific bike, each component part and its supplier:

MATCH
  (:Bike {id: 1})-[HAS_COMPONENT]->(c)-[:IS_PART]->(part),
  (c)-[:SUPPLIED_BY]->(supplier)
RETURN part, supplier;

Upvotes: 3

Related Questions