2
votes

I'm new to NEO4J and I need help on a specific problem. Or an answer if it's even possible.

SETUP: We have 2 distinct type of nodes: users (A,B,C,D) and Products (1,2,3,4,5,6,7,8) Next we have 2 distinct type of relationships between users and products where a users WANTS a Product and where a product is OWNED BY a user.

  1. 1,2 is owned by A
  2. 3,4 is owned by B
  3. 5,6 is owned by C
  4. 7,8 is owned by D

Now

  1. B wants 1
  2. C wants 3
  3. D wants 5

So for now, I have no problems and I created the graph data with no difficulty. My questions starts here. We have a circle, when A wants product 8.

A-[:WANTS]->8-[:OWNEDBY]->D-[:WANTS]->5-[:OWNEDBY]->C-[:WANTS]->3-[:OWNEDBY]->B-[:WANTS]->1-[:OWNEDBY]->A

So we have a distinct pattern, U-[:WANTS]->P-[:OWNEDBY]->U

Now what I want to do is to find the paths toward the start node (initiating user that wants a product) following that pattern. How do I define this using Cypher? Or do I need another way?

Thanks upfront.

2
Are you looking for the shortest path from U to U? If so, this question has been answered before: stackoverflow.com/questions/14893127/cypher-query-shortest-pathean5533
yes I'm looking for the shortest path, but the answer only talks about from-[:LINE*]-to. This answer only has 1 type of relation. I have to different relationships.steven
You can match on multiple relationships, i.e. from-[:LINE|ARROW*]-to. It's in the docs: docs.neo4j.org/chunked/milestone/…ean5533
That's not the answer. That query looks for a relation LINE "or" relation ARROW between two nodes. I'm looking for a relation USER_A WANTS PRODUCT followed by PRODUCT OWNEDBY USER_B like in my examplesteven
I solved it partially myself by introducing an extra relation. Every time I have a this pattern A-[:WANTS]->P-[:OWNEDBY]->D I create a relation D-[:CANHAVE]->A so my cypher becomes START wanter=node(1) MATCH p=(wanter<-[:CANHAVE]-owner<-[:OWNEDBY]-product) RETURN p;steven

2 Answers

1
votes

i got a feeling this can be hacked with reduce and counting every even (every second) relationship:

MATCH p=A-[:OWNEDBY|WANTS*..20]->X
WITH r in relationships(p)
RETURN type(r),count(r) as cnt, 
WHERE cnt=10;

or maybe counting all paths where the number of rels is even:

MATCH p=A-[:OWNEDBY|WANTS*..]->X    
RETURN p,reduce(total, r in relationships(p): total + 1)  as tt
WHERE tt%2=0;

but you graph must have the strict pattern, where all incoming relationship from the set of ownedby and wants must be different from all outgoin relationships from the same set. in other words, this pattern can not exist: A-[:WANTS]->B-[:WANTS]->C or A-[:OWNEDBY]->B-[:OWNEDBY]->C

the query is probably wrong in syntax, but the logic can be implemented in cypher whn you will play more with it. or use gremlin, I think I saw somewhere a gremlin query, where you could define a pattern and than loop n-times via that pattern further till the end node.

0
votes

I've played around with this and created http://console.neo4j.org/?id=qq9v1 showing the sample graph. I've found the following cypher statement solving the issue:

start a=node(1) 
match p=( a-[:WANTS]->()-[:WANTS|OWNEDBY*]-()-[:OWNEDBY]->a ) 
return p 
order by length(p) desc 
limit 1

There is just one glitch: the intermediate part [:WANTS|OWNEDBY*] does not mandate alternating WANT and OWNEDBY chains. As @ulkas stated, this should not be an issue if you take care during data modelling. You might also look into http://api.neo4j.org/current/org/neo4j/graphalgo/GraphAlgoFactory.html to apply graph algorithms from Java code. You might use unmangaged extensions to provide REST access to that.