Graph Model for Product/Delivery Tracking

Hi there,

I am a newbie with Graph Database, so apologies if it a silly question.

I am trying to create a model for product delivery tracking. (Image attached , also attached html code to create model)

Delivery path for Product1, and product2 is as follows.

Supplier1->Dusseldorf->Brisbane->Perth->Product1->Warehouse
Supplier1->Frankfurt->Johannesburg->Perth->Product2->Warehouse

There are thousands such products coming from same Supplier(Supplier1) and landing at Perth Airport and finally delivered to Warehouse.

Question: How can I track the entire path for a particular product, as same path/airport (Perth) is common for multiple products.

Input Parameter (Only Product ID)
Outcome Needed:

For Product1 it should return:
Supplier1->Dusseldorf->Brisbane->Perth->Product1->Warehouse

and for product2 it should return:
Supplier1->Frankfurt->Johannesburg->Perth->Product2->Warehouse

What addition do i need to make to model to achieve this and what will be cypher query for the same.

supplychainWithRiskIndCypher.txt (795 Bytes)![DeliveryTrackingFull|690x288]

Welcome to the community! You should be able to return the path with something like this:

MATCH (p:Product {id: WhateverYourID})
MATCH (w:Warehouse {id:Whatever})
MATCH path = (w)-[:RECEIVES]->(p)-[*]->(your final node destination here)
RETURN path

It doesn't matter that it goes through the same airport, you just need the individual shipment or item id and you can track it this way. Here's a link to Matching in Neo4j that includes paths as well as a similar question to yours How do you return all distinct full paths?. I hope this helps.

Hi MuddyBootsCode,

Thanks for your reply, I tried the query but it returns me both the paths for Product1, which is not correct

Supplier1->Dusseldorf->Brisbane->Perth->Product1<-Warehouse
Supplier1->Frankfurt->Johannesburg->Perth->Product2<-Warehouse

The correct path which i am expecting is

Supplier1->Dusseldorf->Brisbane->Perth->Product1<-Warehouse

Query I tried

MATCH (p:Product {id:"1"})
MATCH (w:Warehouse {name:"Mywarehouse"})
MATCH path = (w)-[:RECEIVES]->(p)<-[*..7]-(:Supplier)
RETURN path

Question do I need to introduce a property called productID in each relationship, to track which path was taken for a product or is there any simpler way to track this.

It would be better to create a product node like

(supplier)-[:PRODUCT]->(product)-[:DELIVER]->(deliver)-[:FREIGHT]->(c).....

It will be even better if you add date node like

(supplier)-[:DATE_SHIPPED]->(date)-[:PRODUCT]->(product)-[:DELIVER]->(deliver)-[:FREIGHT]->(c)....

Also, if you are shipping many products from the same supplier on the same date , then you create a new branch from (date) node to create a second product delivery path.

Hope this works for you.

Thanks ameyasoft for your reply.

I agree its a better model but doesn't solve the purpose completely.

For example if i select Product2 it would return me BOTH Warehouse1 and Warehouse2 (Picture below) as there is a common airport along the path, which is not correct as product 1,2 belong to Warehouse1 and product 3 belongs to Warehouse2

Also, this is just a small sample data there might be several other common airport along the path.

Do we have to attach a product ID along the path i.e. at Airport Node or Relationship Node?

Here is another example

Model returns me both the paths for Product1
but the correct path for Product1 is
Supplier1->Product1->Dusseldorf->Johannesburg->Perth<-Warehouse

DistinctPathHTML.txt (3.8 KB)
DistinctPathCypher.txt (1.0 KB)

The problem here is that all products from different suppliers go to the same final destination airport, "Perth", but the product and warehouse information is not available at the final destination or at any other airports. Accordingly, the system is showing all the warehouses available at the final destination. You should pass the BOL info from airport to airport. Only then the final airport can connect the correct product to the correct warehouse.

Assuming Supplier 1 ships to WareHouse1 and Supplier 2 sends to WareHouse2:
Try this:

match path = (a:Supplier)-[]-(p:Product)-[*..10]-(w:Warehouse)
where a.name = "Supplier1" and p.name = "Product 1" and w.name = "WareHouse1"
return path




I agree we need to pass product info from airport to airport.
So I can either pass it at relationships or node.

I need some help here

I have created a property list in relationships which will hold the product Ids, now the question is how to search the all the relationships and filter on list for product ID

Below query returns the path successfully but I have hard coded the List index to 0

match path= (n1) -[rel*..10] ->(n2) 
where all(rel in relationships(path)where rel.PID[0]=2)
return path

So the question is how can I search all the relationships and filter on list for product ID

So I tried the below query and returns me nothing.

Can you please help me with the query for the same?

match path= (n1) -[rel*..10] ->(n2) 
where all(rel in relationships(path)where [x in rel.PID  where x=2])
return rel

DistinctPathwithIDCypher.txt (995 Bytes) DistinctPathwithIDHTML.txt (3.7 KB)

match path= (n1:Product) -[rel*..10] ->(n2) 
where n1.name = "Product 1" and all(rel in relationships(path) where n1.name in rel.PID)
return path

To get the warehouse node, you need to add PID property to "RECEIVES" relationship with values PID = [1,2] for warehouse 1 and PID = [3] for warehouse 2

Thanks ameyasoft. Thats works :slight_smile: you have been a great help.

However as you suggested , to get the warehouse node, you need to add PID property to "RECEIVES" relationship.

so my question is , is there a way to search of only a particular relationship along the path.
For eg: I just want to search for TRANSPORT relationship along the path and apply filter on them and not for the rest. Is this possible? or is there any alternate solution you can suggest, probably by using WITH clause?

Otherwise i have to attach the Product ID (PID) to every relationship even when its not required which is not ideal.

Try this with this change in line 2
where n1.name = "Product 1" and type(rel) = "TRANSPORT" and n1.name in red.PID
and comment out third line or delete

Please check this: n1.name = "Product 1" and rel.PID = 1 or 2 or 3. If you have an ID property in Product node then you should use n1.ID in rel.PID.

Please check all this and let me know.

Fabulous. It works. Thanks heaps