当同一节点有很多关系时,Neo4jRepository @Query 结果错误
Neo4jRepository @Query result error when there are many relationships for same node
假设我们使用这个简单的图形模型:
@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>
已编辑,因为我完全错过了错误的原因
Spring 当您 return 一个 Ad
节点时,数据将不会填充嵌入节点。为此,您需要一个专门的结果。此外,在您的查询中,您 return has_advertiser
和 is_favourite_to
关系在 Ad
class 中没有映射。它们完全无关紧要。将您的查询更改为
@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
定义一个额外的 属性,它是唯一的并且以后可以用作索引,因为查询不会扩展并导致重负载:您始终匹配整组 Ad
个节点。我强烈建议不要这样做。
这是因为 OGM 认为这是一个模棱两可的模型。如果您将传入关系添加到 User
,您的问题应该得到解决。
更新: 进一步调查,确实是一个bug。打开https://github.com/neo4j/neo4j-ogm/issues/276
解决方法是在 Ad 和 User 中注释所有的 getter 和 setter(并确保@Relationship 注释包含关系类型和方向)。
假设我们使用这个简单的图形模型:
@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>
已编辑,因为我完全错过了错误的原因
Spring 当您 return 一个 Ad
节点时,数据将不会填充嵌入节点。为此,您需要一个专门的结果。此外,在您的查询中,您 return has_advertiser
和 is_favourite_to
关系在 Ad
class 中没有映射。它们完全无关紧要。将您的查询更改为
@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
定义一个额外的 属性,它是唯一的并且以后可以用作索引,因为查询不会扩展并导致重负载:您始终匹配整组 Ad
个节点。我强烈建议不要这样做。
这是因为 OGM 认为这是一个模棱两可的模型。如果您将传入关系添加到 User
,您的问题应该得到解决。
更新: 进一步调查,确实是一个bug。打开https://github.com/neo4j/neo4j-ogm/issues/276
解决方法是在 Ad 和 User 中注释所有的 getter 和 setter(并确保@Relationship 注释包含关系类型和方向)。