【问题标题】:Neo4jRepository @Query result error when there are many relationships for same nodeNeo4jRepository @Query 同一节点有很多关系时结果错误
【发布时间】:2017-03-05 05:42:27
【问题描述】:

假设我们使用这个简单的图模型:

@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
 }

编辑:按照其中一位专家的建议,我尝试将传入关系添加到用户实体,但问题仍然存在。

@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;
   }
}

如果我通过 neo4j 控制台执行密码查询以检索带有广告商和收藏夹信息的广告,它运行良好:

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

但是,如果我改为通过 neo4jRepository 执行查询:

  • advertiser 用户已正确持久化。
  • favourites 集合中有两个用户:总是将广告客户用户添加到集合中,这是不正确的,因为与此用户没有 IS_FAVOURITE_TO 关系。

@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();
 }

我可以更改查询或图形模型中的某些内容来避免这种情况吗? 也许是 spring-data-neo4j 错误?

版本:

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

【问题讨论】:

    标签: java neo4j spring-data-neo4j-4 neo4j-ogm


    【解决方案1】:

    已编辑,因为我完全错过了错误的原因

    当您返回 Ad 节点时,Spring Data 不会填充嵌入式节点。为此,您需要一个专门的结果。此外,在您的查询中,您返回 has_advertiseris_favourite_to 关系,它们在 Ad 类中没有映射。它们完全无关紧要。将您的查询更改为

    @Query("MATCH (advertiser:User)<-[:HAS_ADVERTISER]-(a:Ad)-[:IS_FAVOURITE_TO]->(favourite:User) 
    RETURN a AS ad, advertiser, collect(DISTINCT favourite) AS favourites")
    public List<AdWithAdvertiserAndFavouritesResult getAdsWithAdvertisersAndFavourites()
    

    然后是相应的结果

    @QueryResult
    public class AdWithAdvertiserAndFavouritesResult {
        private Ad ad;
        private User advertiser;
        private List<User> favourites;
    
        //only getters, no setters
    }
    

    您可能需要考虑为 Ad 定义一个附加属性,该属性是唯一的,以后可以用作索引,因为查询不会扩展并导致负载过重:您始终匹配整个 @987654328 集@节点。我强烈建议不要这样做。

    【讨论】:

    • 嗨克里斯托夫。感谢您的回答,但我不确定这是否是重点。我相信我可以在没有@QueryResult 的情况下在这里得到结果。看@Luanne 的回答...反正我还是不能让它工作,所以我会试一试
    【解决方案2】:

    这是因为 OGM 认为这是一个模棱两可的模型。如果您将传入关系添加到User,您的问题应该会得到解决。

    更新:经过进一步调查,这确实是一个错误。已开通https://github.com/neo4j/neo4j-ogm/issues/276

    解决方法是在 Ad 和 User 中注释所有 getter 和 setter(并确保 @Relationship 注释包含关系类型和方向)。

    【讨论】:

    • 谢谢@Luanne,不知道。那么如果两个节点之间存在关系,我是否应该始终将关系添加到两个节点?这是一般规则吗?我会在几个小时内尝试您的建议,如果问题得到解决,我会通知您。谢谢
    • 当您的情况模棱两可时,您对同一实体有两种不同的关系类型,一种是 1:1,一种是 1:n。在其他情况下,您不需要映射双方。让我知道如果这能解决它
    • 嗨@Luanne。我刚刚尝试过您的建议,恐怕问题仍然存在……知道吗?谢谢你的时间。请注意,一种关系是 1:1,另一种是 n:n(不是您在评论中指出的 1:n)。不确定它是否可以相关......
    • 嗯,当您添加传入的 rel 时,您是否使用 @Relationship 指定 INCOMING 来注释字段和 getter/setter? (如果没有,请尝试)
    • 不确定我是否理解正确(不知道getter/setter也可以用@Relationship注释)。我已经尝试过,但都不起作用(请参阅我的问题编辑)我也厌倦了将关系名称添加到 getter/setter,但同样的问题。再次感谢
    猜你喜欢
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    相关资源
    最近更新 更多