Spring Data Neo4j - 无法从自定义查询中获取结果
Spring Data Neo4j - can't get result from custom query
我写了下面的代码来检索 class 个实体。
@Repository
public interface ClassRepository extends ReactiveNeo4jRepository<Class, Long> {
@Query("MATCH (project: Project) WHERE $pid in project.pids " +
"MATCH (c: Class {name: $name})-[:relates*1..$depth]-(target: Class) " +
"RETURN target")
Flux<Class> findClassByName(@Param("name") String name, Long pid, @Param("depth") Long depth);
}
而Class实体就是这个。
@Node("Class")
@ToString
@Getter
@Setter
public class Class {
@GeneratedValue
@Id
private Long id;
private String url;
private String name;
private Boolean isAbstract;
private Boolean isStatic;
@Relationship(type="belongs_to_package", direction = Relationship.Direction.INCOMING)
private Package aPackage;
@Relationship(type = "relates", direction = Relationship.Direction.INCOMING)
private Set<ClassRelationship> classRelates = new HashSet<>();
@Relationship(type = "relates", direction = Relationship.Direction.INCOMING)
private Set<InterfaceRelationship> interfaceRelates = new HashSet<>();
@Relationship(type = "nested", direction = Relationship.Direction.INCOMING)
private Set<Class> nested = new HashSet<>();
public Class(String url, String name, Boolean isAbstract, Boolean isStatic, Package aPackage) {
this.url = url;
this.name = name;
this.isAbstract = isAbstract;
this.isStatic = isStatic;
this.aPackage = aPackage;
}
}
但是它会产生这样的错误...
org.neo4j.driver.exceptions.ClientException: Parameter maps cannot be used in MATCH patterns (use a literal map instead, eg. "{id: {param}.id}") (line 1, column 97 (offset: 96))
"MATCH (project: Project) WHERE $pid in project.pids MATCH (c: Class {name: $name})-[:relates*1..$depth]-(target: Class) RETURN target"
当我将 [:relates*1..$depth] 更改为 [:relates] 时,它不会生成任何错误。所以我知道错误在哪里产生但我不知道为什么会产生错误..
我能为它做什么?
在 Cypher 中不允许使用参数作为 boundary/limit 值。 (https://neo4j.com/docs/cypher-manual/current/syntax/parameters/)
我建议在这里使用 Neo4jTemplate
。
Neo4jTemplate#findAll(Statement statement, Class<T> domainType)
附近的更具体的内容。
此方法让您定义自己的查询,手动创建,例如通过 Cypher-DSL (https://github.com/neo4j-contrib/cypher-dsl/) 来避免由于注入引起的安全问题。
您可以做的其他事情是使用Neo4jClient
,手动创建查询,例如再次使用 Cypher-DSL,并为您的 Project
实体 (https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#neo4j-client.result-objects.mapping-functions)
使用现有的映射函数
简而言之,像这样(没有 Cypher-DSL 部分):
BiFunction<TypeSystem, MapAccessor, Movie> mappingFunction = neo4jMappingContext.getRequiredMappingFunctionFor(Project.class);
Project project = client
.query("<your statement>")
.fetchAs(Project.class).mappedBy((TypeSystem t, Record record) -> {
return record.get("target")
.asList(project -> mappingFunction.apply(t, project));
})
.one();
我写了下面的代码来检索 class 个实体。
@Repository
public interface ClassRepository extends ReactiveNeo4jRepository<Class, Long> {
@Query("MATCH (project: Project) WHERE $pid in project.pids " +
"MATCH (c: Class {name: $name})-[:relates*1..$depth]-(target: Class) " +
"RETURN target")
Flux<Class> findClassByName(@Param("name") String name, Long pid, @Param("depth") Long depth);
}
而Class实体就是这个。
@Node("Class")
@ToString
@Getter
@Setter
public class Class {
@GeneratedValue
@Id
private Long id;
private String url;
private String name;
private Boolean isAbstract;
private Boolean isStatic;
@Relationship(type="belongs_to_package", direction = Relationship.Direction.INCOMING)
private Package aPackage;
@Relationship(type = "relates", direction = Relationship.Direction.INCOMING)
private Set<ClassRelationship> classRelates = new HashSet<>();
@Relationship(type = "relates", direction = Relationship.Direction.INCOMING)
private Set<InterfaceRelationship> interfaceRelates = new HashSet<>();
@Relationship(type = "nested", direction = Relationship.Direction.INCOMING)
private Set<Class> nested = new HashSet<>();
public Class(String url, String name, Boolean isAbstract, Boolean isStatic, Package aPackage) {
this.url = url;
this.name = name;
this.isAbstract = isAbstract;
this.isStatic = isStatic;
this.aPackage = aPackage;
}
}
但是它会产生这样的错误...
org.neo4j.driver.exceptions.ClientException: Parameter maps cannot be used in MATCH patterns (use a literal map instead, eg. "{id: {param}.id}") (line 1, column 97 (offset: 96))
"MATCH (project: Project) WHERE $pid in project.pids MATCH (c: Class {name: $name})-[:relates*1..$depth]-(target: Class) RETURN target"
当我将 [:relates*1..$depth] 更改为 [:relates] 时,它不会生成任何错误。所以我知道错误在哪里产生但我不知道为什么会产生错误..
我能为它做什么?
在 Cypher 中不允许使用参数作为 boundary/limit 值。 (https://neo4j.com/docs/cypher-manual/current/syntax/parameters/)
我建议在这里使用 Neo4jTemplate
。
Neo4jTemplate#findAll(Statement statement, Class<T> domainType)
附近的更具体的内容。
此方法让您定义自己的查询,手动创建,例如通过 Cypher-DSL (https://github.com/neo4j-contrib/cypher-dsl/) 来避免由于注入引起的安全问题。
您可以做的其他事情是使用Neo4jClient
,手动创建查询,例如再次使用 Cypher-DSL,并为您的 Project
实体 (https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#neo4j-client.result-objects.mapping-functions)
简而言之,像这样(没有 Cypher-DSL 部分):
BiFunction<TypeSystem, MapAccessor, Movie> mappingFunction = neo4jMappingContext.getRequiredMappingFunctionFor(Project.class);
Project project = client
.query("<your statement>")
.fetchAs(Project.class).mappedBy((TypeSystem t, Record record) -> {
return record.get("target")
.asList(project -> mappingFunction.apply(t, project));
})
.one();