In cypher, you are asking to find patterns of nodes and relationships. Each found pattern is returned as one result. At first we where looking for users and the books they have read. This can be expressed with the following pattern:
(u:User)-[:HAS_READ]->(b:Book)
This says "fined all User nodes and their related Book nodes, related through a HAS_READ relationships. For each found result, assign the User node to the variable 'u' and the Book node to the variable 'b". The binding to variables is used to reference the entities in your query or return statement.
In your last request, you asked to find the number of books that each user has read in common. To do that, we need to specify a pattern that defines that relationship between two User nodes. The pattern I used was:
(n1:User)-[:HAS_READ]->()<-[:HAS_READ]-(n2:User)
This pattern is asking to find two User nodes that have a HAS_READ relationship to the same entity. In this example, I did not specify the type of node that they have in common (indicated by '()') because I knew from your data model that a User can only have a HAS_READ relationship to a Book node. If this was not the case and you could have a User be related to more than one type of node through a HAS_READ relationships, you can add the "Book" constraint as follows:
(n1:User)-[:HAS_READ]->(:Book)<-[:HAS_READ]-(n2:User)
When you match on the above pattern you will get rows of pairs of Users for each book they have read in common. To count the number of books in common, you can use the "count" aggregation clause. The key is to count the number of books in common for each pair of users. To do this, you use "n1" and "n2" as grouping keys, so the count is done for each distinct pair of nodes "n1" and "n2". This is what this query does. The variables outside the aggregation clause are used to group the rows to aggregate over.
match(n1:User)-[:HAS_READ]->()<-[:HAS_READ]-(n2:User)
return n1, n2, count(*) as noOfCommonBooks
Here is some reading on patterns:
Here is some reading on aggregation functions:
You can change what is shown in the Neo4j Desktop graph view by changing the Label and Relationship type display settings. You do that by clicking on a label or relationship and then selecting what to display in the 'caption'.
In the screenshot below, click on the "HAS_COMMON_BOOKS" relationship type on the right-hand side. The modal shown in the next screenshot will appear. In it, select what property you want shown as the caption.
