arslan
arslan

Reputation: 2234

Neo4j: weighted relationships, how to reflect important relationships in query?

I have data in which some relationships are much important than others and weighted to indicate it. For example, I have the graph like this:

  (city_a:City)-[:has{weight:10}]->(casino:Event)
  (city_a:City)-[:has{weight:1}]->(restaurant:Event)
  (city_a:City)-[:has{weight:30}]->(university:Event)    
  (city_a:City)-[:has{weight:25}]->(library:Event) 
   ......
  (city_b:City)-[:has{weight:2}]->(casino:Event)
  (city_b:City)-[:has{weight:2}]->(restaurant:Event)
  (city_b:City)-[:has{weight:5}]->(university:Event)    
  (city_b:City)-[:has{weight:10}]->(library:Event) 
   ......  

and I have an input as following

  Input: {casino, restaurant, university}

and I should output

  Output: city_a 

as an answer since it has most relationships weighted more than other cities.

(Maybe my graph model is not the right one, but I could not think of something also. advices are very welcomed).

So, how to write cypher query for this case?

Thanks in advance!

Upvotes: 0

Views: 1202

Answers (1)

InverseFalcon
InverseFalcon

Reputation: 30417

Here's an example graph based on your description, with 'city_c' thrown in to cover the case of a city with fewer than the desired input events:

merge (city_a:City{name:'city_a'})
merge (city_b:City{name:'city_b'})
merge (city_c:City{name:'city_c'})

merge (casino:Event{name:'casino'})
merge (restaurant:Event{name:'restaurant'})
merge (university:Event{name:'university'})
merge (library:Event{name:'library'})

merge (city_a)-[:has{weight:10}]->(casino)
merge (city_a)-[:has{weight:1}]->(restaurant)
merge (city_a)-[:has{weight:30}]->(university)    
merge (city_a)-[:has{weight:25}]->(library) 

merge (city_b)-[:has{weight:2}]->(casino)
merge (city_b)-[:has{weight:2}]->(restaurant)
merge (city_b)-[:has{weight:5}]->(university)    
merge (city_b)-[:has{weight:10}]->(library) 

merge (city_c)-[:has{weight:100}]->(university) 

We'll also want an index on :Event(name) for quick lookups by your input strings (you'll probably also want an index on :City(name), though this won't be needed or used with this particular query)

create index on :Event(name)

From this we can create the query to match from input events to cities with those events and order by the number of matching events per city and the sum of the ratings.

Instead of the with ... as input you'd want to parameterize your query.

with ['casino', 'restaurant', 'university'] as input
match (e:Event)<-[r:has]-(city:City)
where e.name in input
with city, count(r) as eventCount, sum(r.weight) as weightSum
return city, eventCount, weightSum
order by eventCount desc, weightSum desc
limit 1

Upvotes: 3

Related Questions