Spring 数据 Neo4j - ORDER BY {order} 失败
Spring Data Neo4j - ORDER BY {order} fails
我有一个查询,结果应根据传递的参数排序:
@Query("""MATCH (u:User {userId:{uid}})-[:KNOWS]-(:User)-[h:HAS_STUFF]->(s:Stuff)
WITH s, count(h) as count ORDER BY count {order}
RETURN o, count SKIP {skip} LIMIT {limit}""")
fun findFromOthersByUserIdAndSortByAmountOfStuff(
@Param("uid") userId: String,
@Param("skip") skip: Int,
@Param("limit") limit: Int,
@Param("order) order: String): List<StuffWithCountResult>
对于 order
参数,我使用以下 enum
及其唯一方法:
enum class SortOrder {
ASC,
DESC;
fun toNeo4JSortOrder(): String {
when(this) {
ASC -> return ""
DESC -> return "DESC"
}
}
}
好像SDN没有正确处理{order}
参数?在执行时,我得到一个异常告诉
Caused by: org.neo4j.kernel.impl.query.QueryExecutionKernelException: Invalid input 'R': expected whitespace, comment or a relationship pattern (line 3, column 5 (offset: 244))
" RETURN o, count SKIP {skip} LIMIT {limit}"
^
如果我从 Cypher 语句中删除参数或将其替换为硬编码 DESC
,则该方法会成功。我相信这不是因为 enum
因为我在其他存储库方法中使用(其他)枚举并且所有这些方法都成功了。我已经尝试过不同的参数命名方式,例如 sortOrder
,但这没有帮助。
我在这里错过了什么?
这是更改 排序 和 分页 信息的错误模型。您可以跳到下面的答案以了解如何使用这些选项,或者继续阅读以了解您的代码目前存在的问题。
您不能在不允许绑定的地方绑定:
您不能将参数绑定到未为 "parameter binding" 设置的查询语法元素中。参数绑定不进行简单的字符串替换(因为您可能会受到注入攻击),而是使用绑定 API 来绑定参数。您正在处理查询注释,就像它正在执行字符串替换一样,但事实并非如此。
parameter binding docs for Neo4J and the Java manual for Query Parameters 准确显示您可以绑定的位置,唯一允许的位置是:
- 代替字符串文字
- 代替正则表达式
- 字符串模式匹配
- 创建具有属性的节点,作为属性
- 创建多个具有属性的节点,作为属性
- 设置节点的所有属性
- SKIP 和 LIMIT 的数值
- 作为节点 ID
- 作为多个节点 ID
- 索引值
- 索引查询
在 ORDER BY 子句中没有任何内容表明您正在尝试的内容是允许的。
这并不是说 Spring Data 的作者无法解决这个问题并允许在其他地方进行绑定,但看起来他们所做的并不比 Neo4J Java API 允许。
您可以改为使用排序 class:
(针对版本 4.2.0.M1
标记了允许此操作的修复,该版本是截至 2016 年 9 月 8 日的预发布版,请参阅下文了解使用里程碑版本)
Spring 数据有一个 Sort
class,如果你的 @Query
注释方法有一个这种类型的参数,它应该应用排序并允许动态修改查询。
我假设代码看起来像(未经测试):
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
List<Actor> getActorsThatActInMovieFromTitle(String movieTitle, Sort sort);
或者您可以使用 PageRequest class / Pageable 接口:
(针对版本 4.2.0.M1
标记了允许此操作的修复,该版本是截至 2016 年 9 月 8 日的预发布版,请参阅下文了解使用里程碑版本)
在当前 Spring Data + Neo4j docs 中,您会看到使用分页的示例:
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
Page<Actor> getActorsThatActInMovieFromTitle(String movieTitle, PageRequest page);
(Spring 数据中 Cypher Examples 的样本 + Neo4j 文档)
而这个 PageRequest
class also allows sorting parameterization. Anything that implements Pageable
也会做同样的事情。使用 Pageable
可能更合适:
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
Page<Actor> getActorsThatActInMovieFromTitle(String movieTitle, Pageable page);
您或许可以在早期版本中使用 SpEL:
作为替代方案,您可以查看 using SpEL expressions 以在查询的其他区域进行替换。我不熟悉它,但它说:
Since this mechanism exposes special parameter types like Sort
or Pageable
as well, we’re now able to use pagination in native queries.
但是official docs好像说比较有限
你应该知道的其他信息:
有人在 GitHub issue. Which then leads to DATAGRAPH-653 issue which was marked as fixed in version 4.2.0.M1
. This references other SO questions here which are outdated so you should ignore those like 中报告了与您完全相同的问题,但已不再正确。
查找 Spring 数据 Neo4j 里程碑构建:
您可以在项目页面上查看 dependencies information for any release。对于 4.2.0.M1
构建 Gradle 的信息(您可以推断 Maven)是:
dependencies {
compile 'org.springframework.data:spring-data-neo4j:4.2.0.M1'
}
repositories {
maven {
url 'https://repo.spring.io/libs-milestone'
}
}
应改用任何较新的最终版本。
我有一个查询,结果应根据传递的参数排序:
@Query("""MATCH (u:User {userId:{uid}})-[:KNOWS]-(:User)-[h:HAS_STUFF]->(s:Stuff)
WITH s, count(h) as count ORDER BY count {order}
RETURN o, count SKIP {skip} LIMIT {limit}""")
fun findFromOthersByUserIdAndSortByAmountOfStuff(
@Param("uid") userId: String,
@Param("skip") skip: Int,
@Param("limit") limit: Int,
@Param("order) order: String): List<StuffWithCountResult>
对于 order
参数,我使用以下 enum
及其唯一方法:
enum class SortOrder {
ASC,
DESC;
fun toNeo4JSortOrder(): String {
when(this) {
ASC -> return ""
DESC -> return "DESC"
}
}
}
好像SDN没有正确处理{order}
参数?在执行时,我得到一个异常告诉
Caused by: org.neo4j.kernel.impl.query.QueryExecutionKernelException: Invalid input 'R': expected whitespace, comment or a relationship pattern (line 3, column 5 (offset: 244))
" RETURN o, count SKIP {skip} LIMIT {limit}"
^
如果我从 Cypher 语句中删除参数或将其替换为硬编码 DESC
,则该方法会成功。我相信这不是因为 enum
因为我在其他存储库方法中使用(其他)枚举并且所有这些方法都成功了。我已经尝试过不同的参数命名方式,例如 sortOrder
,但这没有帮助。
我在这里错过了什么?
这是更改 排序 和 分页 信息的错误模型。您可以跳到下面的答案以了解如何使用这些选项,或者继续阅读以了解您的代码目前存在的问题。
您不能在不允许绑定的地方绑定:
您不能将参数绑定到未为 "parameter binding" 设置的查询语法元素中。参数绑定不进行简单的字符串替换(因为您可能会受到注入攻击),而是使用绑定 API 来绑定参数。您正在处理查询注释,就像它正在执行字符串替换一样,但事实并非如此。
parameter binding docs for Neo4J and the Java manual for Query Parameters 准确显示您可以绑定的位置,唯一允许的位置是:
- 代替字符串文字
- 代替正则表达式
- 字符串模式匹配
- 创建具有属性的节点,作为属性
- 创建多个具有属性的节点,作为属性
- 设置节点的所有属性
- SKIP 和 LIMIT 的数值
- 作为节点 ID
- 作为多个节点 ID
- 索引值
- 索引查询
在 ORDER BY 子句中没有任何内容表明您正在尝试的内容是允许的。
这并不是说 Spring Data 的作者无法解决这个问题并允许在其他地方进行绑定,但看起来他们所做的并不比 Neo4J Java API 允许。
您可以改为使用排序 class:
(针对版本 4.2.0.M1
标记了允许此操作的修复,该版本是截至 2016 年 9 月 8 日的预发布版,请参阅下文了解使用里程碑版本)
Spring 数据有一个 Sort
class,如果你的 @Query
注释方法有一个这种类型的参数,它应该应用排序并允许动态修改查询。
我假设代码看起来像(未经测试):
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
List<Actor> getActorsThatActInMovieFromTitle(String movieTitle, Sort sort);
或者您可以使用 PageRequest class / Pageable 接口:
(针对版本 4.2.0.M1
标记了允许此操作的修复,该版本是截至 2016 年 9 月 8 日的预发布版,请参阅下文了解使用里程碑版本)
在当前 Spring Data + Neo4j docs 中,您会看到使用分页的示例:
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
Page<Actor> getActorsThatActInMovieFromTitle(String movieTitle, PageRequest page);
(Spring 数据中 Cypher Examples 的样本 + Neo4j 文档)
而这个 PageRequest
class also allows sorting parameterization. Anything that implements Pageable
也会做同样的事情。使用 Pageable
可能更合适:
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
Page<Actor> getActorsThatActInMovieFromTitle(String movieTitle, Pageable page);
您或许可以在早期版本中使用 SpEL:
作为替代方案,您可以查看 using SpEL expressions 以在查询的其他区域进行替换。我不熟悉它,但它说:
Since this mechanism exposes special parameter types like
Sort
orPageable
as well, we’re now able to use pagination in native queries.
但是official docs好像说比较有限
你应该知道的其他信息:
有人在 GitHub issue. Which then leads to DATAGRAPH-653 issue which was marked as fixed in version 4.2.0.M1
. This references other SO questions here which are outdated so you should ignore those like
查找 Spring 数据 Neo4j 里程碑构建:
您可以在项目页面上查看 dependencies information for any release。对于 4.2.0.M1
构建 Gradle 的信息(您可以推断 Maven)是:
dependencies {
compile 'org.springframework.data:spring-data-neo4j:4.2.0.M1'
}
repositories {
maven {
url 'https://repo.spring.io/libs-milestone'
}
}
应改用任何较新的最终版本。