如何获取Spring Neo4j密码自定义查询以填充子关系数组 [英] How to get spring neo4j cypher custom query to populate an array of child relationships

查看:79
本文介绍了如何获取Spring Neo4j密码自定义查询以填充子关系数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

默认情况下,对Spring Data Neo4j(SDN)的内置查询将返回深度为1的对象.这意味着将填充查询返回的对象的子级"(相关节点).很好-在这些查询返回的对象的引用的末尾有实际对象.

Built-in queries to Spring Data Neo4j (SDN) return objects populated with depth 1 by default. This means that "children" (related nodes) of an object returned by a query are populated. That's good - there are actual objects on the end of references from objects returned by these queries.

默认情况下,自定义查询的深度为0.这很麻烦.

Custom queries are depth 0 by default. This is a hassle.

此答案中,描述了如何获取springboot neo4j以便将相关元素填充到自定义目标中查询-从查询中获得额外一级的结果深度.

In this answer, it is described how to get springboot neo4j to populate a related element to the target of a custom query - to achieve an extra one level of depth of results from the query.

当相关元素位于列表中时,我在使用此方法时遇到麻烦:

I am having trouble with this method when the related elements are in a list:

@NodeEntity
public class BoardPosition {

    @Relationship(type="PARENT", direction = Relationship.INCOMING)
    public List<BoardPosition> children;

我有一个返回目标BoardPosition的查询,我需要填充它的孩子.

I have a query returning a target BoardPosition and I need it's children to be populated.

@Query("MATCH (target:BoardPosition) <-[c:PARENT]- (child:BoardPosition) 
       WHERE target.play={Play} 
       RETURN target, c, child")
BoardPosition findActiveByPlay(@Param("Play") String play);

问题是查询似乎为每个孩子返回一个单独的结果,而这些结果没有被用来填充目标中的孩子数组.

The problem is that the query appears to return one separate result for each child, and those results aren't being used to populate the array of children in the target.

我得到的是仅预期1个结果"错误,而不是Spring Neo将孩子归类到目标数组中,就像查询正在返回多个结果,每个结果中只有一个孩子,而不是其中一个孩子返回一个结果.

Instead of Spring Neo collating the children into the array on the target, I get "only 1 result expected" error - as if the query is returning multiple results each with one child, rather than one result with the children in it.

org.springframework.dao.IncorrectResultSizeDataAccessException: 结果大小不正确:预期最多为1

org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected at most 1

如何使用自定义查询来填充目标的子列表?

How can I have a custom query to populate that target's children list?

(请注意,内置findByPlay(play)可以满足我的要求-内置查询的深度为1而不是0,它返回一个包含填充子对象的目标-但我当然需要进行查询比玩法"要复杂得多……这就是为什么我需要解决这个问题)

(Note that the built-in findByPlay(play) does what I want - the built-in queries have a depth of 1 rather than 0, and it returns a target with populated children - but of course I need to make the query a bit more sophisticated than just "by Play"... that's why I need to solve this)

版本:

org.springframework.data:spring-data-neo4j:5.1.3.RELEASE

neo4j 3.5.0

推荐答案

===编辑======

出现问题是因为您具有自我关系(相同标签的节点之间的关系)

Your problem arises because you have self-relationship (relationship between nodes of the same label)

这是Spring如何对待单个节点的查询:

This is how Spring treat your query for single node:

org.springframework.data.neo4j.repository.query.GraphQueryExecution

@Override
public Object execute(Query query, Class<?> type) {
    Iterable<?> result;
    ....
    Object ret = iterator.next();
    if (iterator.hasNext()) {
        throw new IncorrectResultSizeDataAccessException("Incorrect result size: expected at most 1", 1);
    }
    return ret;
}

Spring将您的节点类类型Class<?> type传递给neo4j-ogm并回读您的数据.

Spring passes your node class type Class<?> type to neo4j-ogm and have your data read back.

您知道,neo4j服务器将为您的查询返回多个行,每个匹配的path都将返回一行:

You know, neo4j server will returns multiple rows for your query, one for each matching path:

A <- PARENT - B
A <- PARENT - C
A <- PARENT - D

如果您的节点具有不同的标签,即具有不同的类类型,则ogm仅返回单个节点对应于您的查询返回类型,

If your nodes are of different labels, i.e. of different class type then the ogm only return single node correspond to your query return type, no problem.

但是您的节点具有相同的标签,即相同的类类型=> Neo4j OGM无法区分哪个节点是返回的节点->返回的所有节点A,B,C,D->异常

But your nodes are of the same labels, i.e. same class type => Neo4j OGM cannot distinguish which is the returned node -> All nodes A, B, C, D returned -> Exception

关于此问题,我认为您现在应该提交错误报告.

Regard this issue, I think you should file a bug report now.

有关解决方法,您可以更改查询以仅返回distinct target.your_identity_property(identity_property是节点的主键",它唯一地标识您的节点)

For workaround, you can can change the query to return only the distinct target.your_identity_property (identity_property is 'primary key' of the node, which uniquely identify your node)

然后使用that identity属性加载您的应用程序调用:

Then have your application call load with the that identity property:

public interface BoardRepository extends CrudRepository<BoardPos, Long> {

    @Query("MATCH (target:B) <-[c:PARENT]- (child:B) WHERE target.play={Play} RETURN DISTINCT target.your_identity_property")
    Long findActiveByPlay(@Param("Play") String play);

    BoardPos findByYourIdentityProperty(xxxx);
} 

=== OLD ======

Spring文档说 (由我突出显示):

Spring docs says that (highlighted by me):

自定义查询不支持自定义深度.此外,@ Query不支持将路径映射到域实体,因此,不应从Cypher查询中返回路径. 相反,返回节点和关系以将它们映射到域实体.

因此很明显,支持您的用例(通过自定义查询填充子节点). Spring框架已经将结果映射到单个节点中. (实际上,我在本地投票站上的设置表明该操作正常运行

So clearly your use-case (populate children nodes by custom query) is supported. Spring framework already maps the results into a single node. (Indeed, my setup on local turnouts that the operation is working properly)

因此,您的异常可能是由以下几个问题引起的:

So your exception may be caused by several issues:

  1. 您有多个target:BoardPositiontarget.play={play}.因此,该异常是指不止一个target:BoardPosition ,而不是一个具有多个子结果的BoardPosition

  1. You have more than one target:BoardPosition with target.play={play}. So the exception refers to more than one target:BoardPosition instead of one BoardPosition with multiple child result

您的实体映射不正确.您是否使用正确的direction属性用@Relationship注释了您的映射字段?您可以在此处发布您的实体.

You have incorrect entity mapping. Do you have your mapping field annotated with @Relationship with correct direction attribute? You might post your entity here.

这是我的本地设置:

@NodeEntity(label = "C")
@Data
public class Child {

    @Id
    @GeneratedValue
    private long id;
    private String name;

    @Relationship(type = "PARENT", direction = "INCOMING")
    private List<Parent> parents;
}

public interface ChildRepository extends CrudRepository<Child, Long> {

    @Query("MATCH (target:C) <-[p:PARENT]- (child:P) " 
        + "WHERE target.name={name} " 
        + "RETURN target, p, child")
    Child findByName(@Param("name") String name);
}

(:C) <-[:PARENT] - (:P)

这篇关于如何获取Spring Neo4j密码自定义查询以填充子关系数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆