具有自定义查询和复合实体的 Neo4j SDN4 存储库方法
Neo4j SDN4 repository method with custom query and composite entity
我有以下 SDN 4 实体:
@NodeEntity
public class Decision {
@Relationship(type = CONTAINS, direction = Relationship.INCOMING)
private Set<Decision> parentDecisions;
...
}
我想通过 id 和 return 所有 parentDecisions
找到这个实体,使用以下 SDN4 存储库方法和自定义 Cypher 查询:
MATCH (d:Decision) WHERE d.id = {decisionId} OPTIONAL MATCH (d)<-[rdp:CONTAINS]-(parentD:Decision) RETURN d, rdp, parentD
Decision getById(@Param("decisionId") Long decisionId);
现在,如果存在 parentD
,它会失败,但出现以下异常:
java.lang.RuntimeException: Result not of expected size. Expected 1 row but found 3
at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.queryForObject(ExecuteQueriesDelegate.java:73)
at org.neo4j.ogm.session.Neo4jSession.queryForObject(Neo4jSession.java:382)
at sun.reflect.GeneratedMethodAccessor111.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
如何使用 SDN4 存储库方法和自定义 Cypher 查询正确实现此逻辑?
已更新
我测试了frant.hartm建议的方法。不幸的是,它仍然不起作用。
例如下面的SDN4存储库方法正确returns 2 Decision
:
@Query("MATCH (d:Decision)-[drd:FOLLOWS]->(following:Decision) WHERE d.id = {decisionId} RETURN following")
List<Decision> test(@Param("decisionId") Long decisionId);
但是下一个:
@Query("MATCH (d:Decision) WHERE d.id = {decisionId} OPTIONAL MATCH (d)-[rdf:FOLLOWS]->(followD:Decision) RETURN d as decision, collect(rdf), collect(followD) ")
DecisionHolder test1(@Param("decisionId") Long decisionId);
return 仅主要 decision
(holder.getDecision()
) 但具有 followD
(holder.getDecision().getFollowDecisions()
) 决策的空集合。
这是Decision
实体:
@NodeEntity
public class Decision {
private static final String FOLLOWS = "FOLLOWS";
@Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
private Set<Decision> followDecisions;
@Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
public Set<Decision> getFollowDecisions() {
return followDecisions;
}
@Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
public void setFollowDecisions(Set<Decision> followDecisions) {
this.followDecisions = followDecisions;
}
....
}
我做错了什么?
核心问题是你的查询returns多个Decision
实例(在不同的变量下-d
和parentD
),所以不能随意选择一。使用 @QueryResult
提取所需的值。同样使用 COLLECT
得到一个结果。
@QueryResult
public class DecisionHolder {
Decision d;
}
MATCH (d:Decision) WHERE d.id = {decisionId} " +
"OPTIONAL MATCH (d)<-[rdp:CONTAINS]-(parentD:Decision) " +
"RETURN d, collect(rdp), collect(parentD)")
DecisionHolder getById(@Param("decisionId") Long decisionId);
更新:
为了正确映射关系实体和具有相同类型的简单关系,不得混合使用。
如果您有简单的关系和相同类型的关系实体
当它们表示相同的关系类型时,请在您的关系定义中使用关系实体 class(例如 Set<ParentDecisionRelationship> parentDecisions
)
当它们代表不同的类型时重命名其中一个
我有以下 SDN 4 实体:
@NodeEntity
public class Decision {
@Relationship(type = CONTAINS, direction = Relationship.INCOMING)
private Set<Decision> parentDecisions;
...
}
我想通过 id 和 return 所有 parentDecisions
找到这个实体,使用以下 SDN4 存储库方法和自定义 Cypher 查询:
MATCH (d:Decision) WHERE d.id = {decisionId} OPTIONAL MATCH (d)<-[rdp:CONTAINS]-(parentD:Decision) RETURN d, rdp, parentD
Decision getById(@Param("decisionId") Long decisionId);
现在,如果存在 parentD
,它会失败,但出现以下异常:
java.lang.RuntimeException: Result not of expected size. Expected 1 row but found 3
at org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.queryForObject(ExecuteQueriesDelegate.java:73)
at org.neo4j.ogm.session.Neo4jSession.queryForObject(Neo4jSession.java:382)
at sun.reflect.GeneratedMethodAccessor111.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
如何使用 SDN4 存储库方法和自定义 Cypher 查询正确实现此逻辑?
已更新
我测试了frant.hartm建议的方法。不幸的是,它仍然不起作用。
例如下面的SDN4存储库方法正确returns 2 Decision
:
@Query("MATCH (d:Decision)-[drd:FOLLOWS]->(following:Decision) WHERE d.id = {decisionId} RETURN following")
List<Decision> test(@Param("decisionId") Long decisionId);
但是下一个:
@Query("MATCH (d:Decision) WHERE d.id = {decisionId} OPTIONAL MATCH (d)-[rdf:FOLLOWS]->(followD:Decision) RETURN d as decision, collect(rdf), collect(followD) ")
DecisionHolder test1(@Param("decisionId") Long decisionId);
return 仅主要 decision
(holder.getDecision()
) 但具有 followD
(holder.getDecision().getFollowDecisions()
) 决策的空集合。
这是Decision
实体:
@NodeEntity
public class Decision {
private static final String FOLLOWS = "FOLLOWS";
@Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
private Set<Decision> followDecisions;
@Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
public Set<Decision> getFollowDecisions() {
return followDecisions;
}
@Relationship(type = FOLLOWS, direction = Relationship.INCOMING)
public void setFollowDecisions(Set<Decision> followDecisions) {
this.followDecisions = followDecisions;
}
....
}
我做错了什么?
核心问题是你的查询returns多个Decision
实例(在不同的变量下-d
和parentD
),所以不能随意选择一。使用 @QueryResult
提取所需的值。同样使用 COLLECT
得到一个结果。
@QueryResult
public class DecisionHolder {
Decision d;
}
MATCH (d:Decision) WHERE d.id = {decisionId} " +
"OPTIONAL MATCH (d)<-[rdp:CONTAINS]-(parentD:Decision) " +
"RETURN d, collect(rdp), collect(parentD)")
DecisionHolder getById(@Param("decisionId") Long decisionId);
更新:
为了正确映射关系实体和具有相同类型的简单关系,不得混合使用。
如果您有简单的关系和相同类型的关系实体
当它们表示相同的关系类型时,请在您的关系定义中使用关系实体 class(例如
Set<ParentDecisionRelationship> parentDecisions
)当它们代表不同的类型时重命名其中一个