neo4j / neo4j-ogm

Java Object-Graph Mapping Library for Neo4j
https://neo4j.com/docs/ogm-manual/
Apache License 2.0
337 stars 164 forks source link

Neo4j Embedded Driver - Object Mapping does not work when relationship is returned from Query #277

Closed srv25273 closed 6 years ago

srv25273 commented 8 years ago

I have posted the same query in StackOverFlow as well, but did not received any feedback and/or suggestions. Thus, posting the same here as well. I am sorry for the redundancy, but I am kind of stuck with this.

Following are the dependency versions I am using for my project:

SDN = 4.1.2.RELEASE
neo4j-ogm = 2.0.3
Embedded Driver = 2.0.3
Spring = 4.3.2.RELEASE
Neo4j Database = 2.3.1-Community
The Domains Look like

The Domains Look like

@NodeEntity
public class StudentNode {

    @GraphId
    Long id;

    private String name;

    @Relationship(type = "hasSubjects", direction = "OUTGOING")
    private List<SubjectNode> subject = new ArrayList<>();

// getters and setters..... 
}

@NodeEntity
public class SubjectNode {
    @GraphId
    Long id;

    private String code;

    @Relationship(type = "hasInstructor", direction = "OUTGOING")
    private List<InstructorNode> instructorList = new ArrayList<>();

    @Relationship(type = "hasBooks", direction = "INCOMING")
    private List<BookNode> books = new ArrayList<BookNode>();

    //getters and setters....
}

@Repository public interface StudentRepo extends GraphRepository {

@Query("MATCH (s:StudentNode)-[r:hasSubjects]-(sub:SubjectNode) WHERE s.name = {name} RETURN r")
StudentNode findStudentByName(@Param("name")String name);

}
and my configuration class looks like :

@EnableAutoConfiguration
@Configuration
@EnableTransactionManagement
@ComponentScan( basePackages = { Graph.GRAPH_PKG} )
@EnableNeo4jRepositories(Graph.GRAPH_REP)
public class LocalConfig extends Neo4jConfiguration {

    @Bean
    public org.neo4j.ogm.config.Configuration getConfiguration() {
        org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration();
        config
                .driverConfiguration()
                .setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver");
        return config;
    }

    @Bean
    @Override
    public Session getSession() throws Exception {
        return super.getSession();
    }

    @Override
    public SessionFactory getSessionFactory() {
       return new SessionFactory(getConfiguration(), Graph.GRAPH_PKG);
//        return new SessionFactory(Graph.GRAPH_PKG);
    }
}

Now in order to save/retrieve my domain object following code snippet is used :

studentRepo.save(student);
StudentNode studentNode = studentRepo.findStudentByName("Sourav");

after executing the above statements with Embedded Driver, null is returned from studentRepo.findStudentByName("Sourav"). However, when executed with HTTP Driver studentNode is assigned with appropriate object. Also, the same code works well with InProcessServer which is deprecated now.

As per the SDN 4 documentation, Return of Path from the query is not supported however, return of nodes and relationship is supported. I am a bit confused on the behavior of Embedded Driver. Is this a bug or I am missing some configuration?

┆Issue is synchronized with this Asana task

mangrish commented 8 years ago

@srv25273 can you try:

@Repository
public interface StudentRepo extends GraphRepository {

    @Query("MATCH (s:StudentNode)-[r:hasSubjects]-(sub:SubjectNode) WHERE s.name = {name} RETURN s, r, sub")
    StudentNode findStudentByName(@Param("name")String name);
}

This should work on all drivers. Let me know how you go.

srv25273 commented 8 years ago

Thanks for the reply. This is the work around I am leaving with at the moment in which the node also needs to be returned along with relationship. However, similar queries are there in multiple places in my project and I have to changed all the query which are returning only relationships. I am curious to know why the behavior is not consistent as compared to HTTP driver. The same query should work in both right?

mangrish commented 8 years ago

To be honest I think it's an implementation detail. There is no specific QoS that the embedded, http or bolt drivers need to adhere to. In any case i would recommend always returning all "end point" type nodes in a query to be complete.

vince-bickers commented 8 years ago

@srv25273 Thanks for bringing this to our attention. I think the expectation that queries should produce the same results when executed by different drivers is a reasonable one, and we need to document where this isn't the case.

In the case of the HTTP driver, we use the graph response format for most queries, which means the JSON representation of a relationship always includes details of its start and end nodes. The bolt and embedded drivers don't get the same data in this case - they are handed individual relationship objects directly via the Neo4j Java driver or by the embedded database instance respectively, with no node details, hence the difference in behaviours. However because it probably makes no sense to return a relationship that can't be attached to anything, I would echo @mangrish advice: always return the endpoints of all relationships.

srv25273 commented 8 years ago

@vince-bickers Thanks for the enlightenment. Now it is kind of clear to me why the behavior is consistent in previous releases ( Neo4j OGM 1.xx ) where InProcess Servers were used. Consequently, In my project all of the queries were returning relationship with a contract that the endpoints would be mapped implicitly and these queries are quite a large in numbers. However, I do not mind making things perfect/consistent even if it takes some effort. Rather, I am delighted to know that you sense a requirement to update the documentation for Drivers with respect to the deviation in behavior. Indeed it would make lots of sense to highlight this as a part of migration steps.

Also, I feel that session handling and support for multiple scopes ( Singleton, session, Prototype, Thread...) needs to be mentioned in the documentation with further clarity for SDN 4.1.X and Neo4J OGM 2.0.X versions. I had some discussion regarding the same with @mangrish on SO.

Kindly let me know your views on the same.

frant-hartm commented 6 years ago

Updated docs - for a relationship to be mapped both start and end node must be returned.