Search code examples
javaspring-bootneo4jspring-data-neo4jneo4j-ogm

Replace @QueryResult while switching from SDN+OGM to SDN/RX


Using up to Spring Boot 2.3.4, I've been using the @QueryResult annotation to map some custom Cypher queries responses to POJOs. I'm now testing the Spring Boot 2.4 first RC and trying to follow instructions on how to drop OGM since the support has been removed. I successfully replaced other annotations by the ones provided here: https://neo4j.github.io/sdn-rx/current/#migrating but I'm now left with my @QueryResult annotations for which nothing is specified. When I delete them I get Mapping errors:

org.springframework.data.mapping.MappingException: Could not find mappable nodes or relationships inside Record

I've looked up some of the Mapping explanations but here's the thing: my custom POJOs don't represent any entity from the database, neither do they represent part(s) of an entity. They're rather relevant bits from differents Nodes. Let me examplify: I want to get all b nodes that are targets of the MY_REL relationship from a:

(a:Node {label:"my label"})-[:MY_REL]->(b:Node)

For my purposes, I don't need to get the nodes in the response, so my POJO only has 2 attributes:

  • a "source" String which is the beginning node's label
  • a "targets" Set of String which is the list of end nodes' labels

and I return this:

RETURN a.label AS source, COLLECT(b.label) AS targets

My POJO was simply annotated with @QueryResult in order to get the mapping done. Does anyone know how to reproduce this behaviour with SB 2.4 release candidate? As I said, removing the now faulty annotation prompts me with a Mapping error but I don't know what I should do to replace it.


Solution

  • Spring Data Neo4j 6 now supports projections (formerly known as @QueryResult) in line with the other Spring Data modules. Having said this, the simplest thing you would have to do, assuming that this @Query is written in a Neo4jRepository<Node,...>, would be to return also the a.

    I know that this sounds ridiculous first but with choosing the repository abstraction, you say that everything that should get processed during the mapping phase is a Node and you want to project its properties (or a subset) into the POJO (DTO projection). SDN cannot ensure that you are really working with the right type when it starts the mapping, so it throws the exception you are facing. Neo4j-OGM was more relaxed behind the scenes for mapping the @QueryResults but unfortunately also wrong with this direction.

    If your use-case is simple as you have described it, I would strongly suggest to use the Neo4jClient(docs) that gives you direct access to the mapping. It has a fluent API for querying and manual mapping, and it participates in the ongoing Spring transactions your repositories are running within.

    There is a lot in there when it comes to projections, so I would suggest to also read the section in the documentation.