Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query to show second degree (indirect) relationships in Neo4j

Tags:

neo4j

cypher

I have a graph with Books, Chapters, and Characters. Books contain Chapters, and Chapters mention Characters. I want to write a query showing me the 10 Characters that appear in most books, together with the books they appear in.

Supposing that my problem is a bit simpler, I can easily write a query showing me the 10 Characters that appear in most chapters:

MATCH (chapter)-[:MENTIONS]->(character)
RETURN character,
COLLECT(chapter) as chapters
ORDER BY SIZE(chapters) DESC
LIMIT 10

This query above is working fine. Now I'm attempting to write a similar query that shows books rather than chapters:

MATCH (book)-[:CONTAINS]->(chapter)-[:MENTIONS]->(character)
RETURN character,
COLLECT(book) as books
ORDER BY SIZE(books) DESC
LIMIT 10

This query seems to work fine, but it just reports a bunch of characters and books without any relationship, because there is no direct relationship between books and characters. Can neo4j infer these indirect relationships and show them in the query without me having to modify the data and manually insert for each pattern

(book)-[:CONTAINS]->(chapter)-[:MENTIONS]->(character)

a new relationship

(book)-[:TALKS_ABOUT]->(character)

?

like image 423
st1led Avatar asked Oct 20 '25 10:10

st1led


1 Answers

It's look like you need virtual relationships. You can try apoc.create.vRelationship:

MATCH (book)-[:CONTAINS]->(chapter)-[:MENTIONS]->(character)
WITH character, 
     COLLECT(distinct book) as books 
     ORDER BY SIZE(books) DESC LIMIT 10
UNWIND books as book
CALL apoc.create.vRelationship(book,'TALKS_ABOUT',{}, character) yield rel
RETURN character, collect(rel) as rels
like image 76
stdob-- Avatar answered Oct 22 '25 00:10

stdob--