Search code examples
javaneo4jspring-data-neo4j-4neo4j-ogm

Neo4jRepository @Query result error when there are many relationships for same node


Let's suppose we use this simple graph model:

@NodeEntity
class Ad {    
    // GraphId and more Ad attributes...

    @Relationship(type = "HAS_ADVERTISER", direction = Relationship.OUTGOING)
    private User advertiser;

    @Relationship(type = "IS_FAVOURITE_TO", direction = Relationship.OUTGOING)
    private Set<User> favourites = new HashSet<>();

    // Getters and setters
 }

EDIT: Following the advises of one of the aswers, I've tried adding the incoming relationships to User entity, but the problem still remains.

@NodeEntity
class User {
    // User attributes. No incoming relationships for HAS_ADVERTISER neither IS_FAVOURITE_TO...

   // EDIT: Added incoming relationships to User entity, but the problem still remains. Tried annotating getters/setters, but neither works
   @Relationship(type = "HAS_ADVERTISER", direction = Relationship.INCOMING)
   private Set<Ad> ads = new HashSet<>();

   @Relationship(type = "IS_FAVOURITE_TO", direction = Relationship.INCOMING)
   private Set<Ad> favourites = new HashSet<>();

   @Relationship(direction = Relationship.INCOMING)
   public Set<Ad> getAds() {
       return ads;
   }

   @Relationship(direction = Relationship.INCOMING)
   public void setAds(Set<Ad> ads) {
       this.ads = ads;
   }

   @Relationship(direction = Relationship.INCOMING)
   public Set<Ad> getFavourites() {
       return favourites;
   }

   @Relationship(direction = Relationship.INCOMING)
   public void setFavourites(Set<Ad> favourites) {
       this.favourites = favourites;
   }
}

If I execute a cypher query to retrieve the ads with advertiser and favourites information through neo4j console, it's simply working well:

MATCH (ad:Ad),
(ad)-[has_advertiser:HAS_ADVERTISER]->(advertiser:User),
(ad)-[is_favourite_to: IS_FAVOURITE_TO] -> (favouriteUser:User)
return ad, has_advertiser, advertiser, is_favourite_to, favouriteUser

enter image description here

However, if I execute the query through a neo4jRepository instead:

  • advertiser user is persisted correctly.
  • There are two users in favourites set: the advertiser user is always added to the set, which is incorrect because there is no IS_FAVOURITE_TO relationship with this user.

@Repository
public interface AdRepository extends Neo4jRepository<Ad> {

    @Query("MATCH (ad:Ad)," +
            "(ad)-[has_advertiser:HAS_ADVERTISER]->(advertiser:User)," +
            "(ad)-[is_favourite_to: IS_FAVOURITE_TO] -> (favouriteUser:User)" +
            "return ad, has_advertiser, advertiser, " +
            "is_favourite_to, favouriteUser ")
    List<Ad> findAds();
 }

enter image description here

Can I change something in my query or my graph model to avoid this? Maybe a spring-data-neo4j bug?

Versions:

<spring-data-neo4j.version>4.2.0.M1</spring-data-neo4j.version>
<neo4j.ogm.version>2.0.5</neo4j.ogm.version>

Solution

  • This is due to the fact that the OGM considers this to be an ambiguous model. If you add the incoming relationships to User, your issue should be resolved.

    Update: upon further investigation, this is indeed a bug. Opened https://github.com/neo4j/neo4j-ogm/issues/276

    The workaround is to annotate all your getters and setters (and make sure the @Relationship annotation contains both the relationship type and the direction) in both Ad and User.