Search code examples
neo4jcypherspring-data-neo4j

Neo4J Group results together rather than multiple results based on matches/relationships


I have a pretty 'simple' Graph which I interact with via Spring Data (and the Neo4J browser).

Currently the Graph has nodes of Books, Publishers and Authors (with relations AUTHOR_OF and PUBLISHES respectivly). A Book can have a single Publisher and multiple Authors.

I'm trying to write a query to find all potential books, their authors and their publisher (if they have them) based on various matches: WHERE unique Id match OR does it match the ISBN OR if the book has an author does it match on book title AND author.

However, the result set returned seems to vary based on the number of relationships as well as the number of criteria it's matched.

My sample data is as follows:

Neo4J Sample data

MATCH (bo:Book)
OPTIONAL MATCH (au:Author)-[r:AUTHOR_OF]->(bo:Book)<-[s:PUBLISHES]-(pu:Publisher)
RETURN bo, r, au, s, pu

Returns three records:

  1. Book 1 with Publisher 'Establishment' and Author 'Doe'
  2. Book 1 with Publisher 'Establishment' and Author 'Bloggs
  3. Book 2
MATCH (bo:Book)
WHERE bo.bookId={book 1 ID}
OPTIONAL MATCH (au:Author)-[r:AUTHOR_OF]->(bo:Book)
OPTIONAL MATCH (bo:Book)<-[s:PUBLISHES]-(pu:Publisher)
RETURN bo, r, au, s, pu

Returns two records.

  1. Book 1 with Publisher 'Establishment' and Author 'Doe'
  2. Book 1 with Publisher 'Establishment' and Author 'Bloggs'
MATCH (bo:Book)
WHERE bo.bookId={book 2 ID}
OPTIONAL MATCH (au:Author)-[r:AUTHOR_OF]->(bo:Book)
OPTIONAL MATCH (bo:Book)<-[s:PUBLISHES]-(pu:Publisher)
RETURN bo, r, au, s, pu

Returns Book 2

MATCH (bo:Book)
WHERE bo.bookId={book 2 ID}
OR bo.isbn={book 1 ISBN}
OPTIONAL MATCH (au:Author)-[r:AUTHOR_OF]->(bo:Book)
OPTIONAL MATCH (bo:Book)<-[s:PUBLISHES]-(pu:Publisher)
RETURN bo, r, au, s, pu

Returns three records

  1. Book 1 with Publisher 'Establishment' and Author 'Doe'
  2. Book 1 with Publisher 'Establishment' and Author 'Bloggs
  3. Book 2

So I appear to be on the right track... However there are couple of things I'm now stumped on.

  1. How to group the results. I want to receive Book 1 with publisher 'Establishment' and Authors 'Doe' and 'Bloggs'
  2. **Add a final or, which matches if theres an author, mathches on author name and book title. This should also return all authors of the book, not just the one it matched on.

I expect the answer lies within a combination of WITH, COLLECT() and DISTINCT but I haven't been successful.


Solution

  • Try something like this, you will need to COLLECT, to collect all authors in a list:

    MATCH (bo:Book)
    WHERE bo.bookId={bookID} OR bo.isbn={bookISBN} OR (bo.title={bookTitle} AND (bo)<-[:AUTHOR_OF]-(:Author{name:{authorName}}))
    OPTIONAL MATCH (au:Author)-[r:AUTHOR_OF]->(bo:Book)
    OPTIONAL MATCH (bo:Book)<-[s:PUBLISHES]-(pu:Publisher)
    RETURN bo, pu, collect(au) AS authors