-
Notifications
You must be signed in to change notification settings - Fork 617
Count() aggregator NoRootNodeMappingException #2633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for using our stuff. It’s for the exact reason the message says: there’s a no node in your result set, just an arbitrary row. This project is not a row mapper, it’s a graph mapper. And yes, simple solution just have a look at the fields of the record and just map them to class names works in that case but the next Ticket than will ask for nested results. However, we will think about whether we can support this simple case with a reasonable amount of work. |
Thanks @michael-simons for the quick reply. It is really clear by extends Neo4jRepository<THENODE, ID> that it needs to be using a actual node. I was in a kind of negation. Seems you got the point. The next natural questions that arise is how to get nested resulted. The 'weird feeling' is that seems this project has all technology capabilities to handle that by Neo4jRepository but chosed not. What I understand is I need create 'on-fly' a new node with a new Neo4jRepository<RESULT_NODE,ID> to fetch this result. Of course lot more work than just by neo4jClient. I'll try to get my 'hands dirty' as a study exercise on how I think this should be and arise a PR. I think you be a fun project. In the worst I'll learn a lot. Do you have a suggestions on how should I start? |
Hey no worries. We spoke about that today how strict do we want to keep things in the repository thing way and let's be honest: It's not the first time a question like this has been raised. It seems that I can make this work with little effort. You see what is necessary to shape up the content (which is also documented anyway for known entities and custom queries): package org.springframework.data.neo4j.integration.lite;
import java.util.Collection;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
/**
* @author Michael J. Simons
*/
public interface SomeDomainRepository extends Neo4jRepository<SomeDomainObject, UUID> {
/**
* @return Mapping arbitrary, ungrouped results into a dto
*/
// language=cypher
@Query("UNWIND range(1,10) AS x RETURN randomUUID() AS resyncId, tointeger(x*rand()*10)+1 AS counter ORDER BY counter")
Collection<MyDTO> getAllFlat();
/**
* @return Mapping a single ungrouped result
*/
// language=cypher
@Query("RETURN randomUUID() AS resyncId, 4711 AS counter")
Optional<MyDTO> getOneFlat();
/**
* @return Mapping a dto plus known domain objects
*/
// language=cypher
@Query("""
MATCH (u:User {login:'michael'}) -[r:OWNS] -> (s:SomeDomainObject)
WITH u, collect(r) AS r, collect(s) AS ownedObjects
RETURN
u{.*, __internalNeo4jId__: id(u), r, ownedObjects} AS user,
randomUUID() AS resyncId, 4711 AS counter,u
""")
Collection<MyDTO> getNestedStuff();
/**
* @return Mapping nested dtos
*/
// language=cypher
@Query("RETURN 'av' AS outer, {inner: 'bv'} AS nested")
Optional<A> getOneNestedDTO();
} |
We can support many more usecases of "I want to have a lightweight mapping tool" for DTOs by just restricting the cases in which a `NoRootNodeMappingException` is thrown. The idea is as follows: If the `DefaultNeo4jEntityConverter` does not deal with a synthesized record comming from `AggregatingMappingFunction` it uses the the root map as base for mapping if the root record is already a map value. If that is not the case and the root record does not contain any paths that maybe aggregated later one, we synthesize a map one single time and evaluate that for being mappable. Closes #2633.
Please have a look the linked PR @goldman7911, the change is basically all in the |
Amazing @michael-simons ! |
We can support many more usecases of "I want to have a lightweight mapping tool" for DTOs by just restricting the cases in which a `NoRootNodeMappingException` is thrown. The idea is as follows: If the `DefaultNeo4jEntityConverter` does not deal with a synthesized record comming from `AggregatingMappingFunction` it uses the the root map as base for mapping if the root record is already a map value. If that is not the case and the root record does not contain any paths that maybe aggregated later one, we synthesize a map one single time and evaluate that for being mappable. Closes #2633.
We can support many more usecases of "I want to have a lightweight mapping tool" for DTOs by just restricting the cases in which a `NoRootNodeMappingException` is thrown. The idea is as follows: If the `DefaultNeo4jEntityConverter` does not deal with a synthesized record comming from `AggregatingMappingFunction` it uses the the root map as base for mapping if the root record is already a map value. If that is not the case and the root record does not contain any paths that maybe aggregated later one, we synthesize a map one single time and evaluate that for being mappable. Closes #2633.
We can support many more usecases of "I want to have a lightweight mapping tool" for DTOs by just restricting the cases in which a `NoRootNodeMappingException` is thrown. The idea is as follows: If the `DefaultNeo4jEntityConverter` does not deal with a synthesized record comming from `AggregatingMappingFunction` it uses the the root map as base for mapping if the root record is already a map value. If that is not the case and the root record does not contain any paths that maybe aggregated later one, we synthesize a map one single time and evaluate that for being mappable. Closes #2633.
We can support many more usecases of "I want to have a lightweight mapping tool" for DTOs by just restricting the cases in which a `NoRootNodeMappingException` is thrown. The idea is as follows: If the `DefaultNeo4jEntityConverter` does not deal with a synthesized record comming from `AggregatingMappingFunction` it uses the the root map as base for mapping if the root record is already a map value. If that is not the case and the root record does not contain any paths that maybe aggregated later one, we synthesize a map one single time and evaluate that for being mappable. Closes #2633.
Hi all,
I have created a replicable repo for this issue: https://github.com/goldman7911/spring-data-understanding
It will need a clear Neo4j running and run tests to validate what I'll try to explain here.
I'm starting feeling there is something wrong or my understanding is complety wrong for OGM
My data is:
My objective is to map this Query to Java:
As you can see, all methods getResyncIdAndMessageIdsCountPureSDNXXXX are failing with same error
org.springframework.data.neo4j.core.mapping.NoRootNodeMappingException: Could not find mappable nodes or relationships inside Record<{resyncId: "fake-7777-4ab1-7777-fake", counter: 2}> for org.springframework.data.neo4j.core.mapping.DefaultNeo4jPersistentEntity@777d191f
Is weird how the same Neo4jRepository uses neo4jClient behind the scenes but could not map it. This method bellow I could sucessfully use in MyService.java
Also, just the first two of MyRepository do work. The 3 left receive the same error NoRootNodeMappingException.
Please help me understand why I can't map count aggregator result as Long by using OGM
The text was updated successfully, but these errors were encountered: