Spring Data Neo4j – ORDER BY {order}失败
我有一个查询结果应根据传递的参数进行排序:
@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
,但这并没有帮助。
我在这里错过了什么?
这是改变排序和分页信息的错误模型。 您可以跳到下面的答案中使用这些选项,或继续阅读以解释代码中的错误。
你不能绑定不允许绑定的地方:
您不能将参数绑定到查询的语法元素中,该参数不是为“参数绑定”设置的。 参数绑定不会执行简单的字符串替换(因为您将打开注入式攻击),而是使用绑定API来绑定参数。 您正在处理查询注释,因为它正在执行字符串替换,而这不是正在发生的事情。
Neo4J的参数绑定文档和查询参数的Java手册显示了你可以绑定的地方 , 唯一允许的地方是:
- 代替字符串文字
- 代替正则表达式
- 字符串模式匹配
- 创建具有属性的节点作为属性
- 创建具有属性的多个节点作为属性
- 设置节点的所有属性
- SKIP和LIMIT的数值
- 作为节点ID
- 作为多个节点ID
- 指数值
- 索引查询
没有什么说你正在尝试的是允许的,在ORDER BY子句中绑定。
这并不是说Spring Data的作者不能解决这个问题,并且允许在其他地方进行绑定,但是看起来他们做的不是Neo4J Java API允许的。
您可以改为使用Sort类:
( 允许的修正标记为版本4.2.0.M1
,该版本是截至2016年9月8日的预发布版本,请参阅下面的使用里程碑版本 )
Spring Data有一个Sort
类 ,如果你的@Query
注解方法有一个这种类型的参数,它应该应用排序并允许它动态地修改查询。
我假设代码看起来像(未经测试):
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor") List<Actor> getActorsThatActInMovieFromTitle(String movieTitle, Sort sort);
或者你可以使用PageRequest类/ Pageable接口:
( 允许的修正标记为版本4.2.0.M1
,该版本是截至2016年9月8日的预发布版本,请参阅下面的使用里程碑版本 )
在当前的Spring Data + Neo4j文档中,您将看到使用分页的示例:
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor") Page<Actor> getActorsThatActInMovieFromTitle(String movieTitle, PageRequest page);
( 来自Spring Data + Neo4j文档中Cypher示例的示例 )
而这个PageRequest
类也允许排序参数化。 任何实现Pageable
都会做同样的事情。 使用Pageable
可能更合适:
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor") Page<Actor> getActorsThatActInMovieFromTitle(String movieTitle, Pageable page);
您可能可以在早期版本中使用SpEL:
作为替代,您可以查看使用SpEL表达式在查询的其他区域进行替换。 我不熟悉它,但它说:
由于这种机制也暴露了像
Sort
或Pageable
这样的特殊参数类型,所以我们现在可以在本地查询中使用分页了。
但官方的文件似乎说这是更有限的。
而且你应该知道这个其他的信息:
这里有人在GitHub问题中报告完全相同的问题 。 然后导致在版本4.2.0.M1
被标记为固定的DATAGRAPH-653问题。 这里引用的其他SO问题已经过时了,所以你应该忽略那些像Spring Data Neo4j 4中的Paging和排序那些不正确的东西。
查找Spring数据Neo4j里程碑构建:
您可以在项目页面上查看任何发行版的依赖关系信息 。 而对于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' } }
任何更新的最终版本应该用来代替。