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表达式在查询的其他区域进行替换。 我不熟悉它,但它说:

由于这种机制也暴露了像SortPageable这样的特殊参数类型,所以我们现在可以在本地查询中使用分页了。

但官方的文件似乎说这是更有限的。

而且你应该知道这个其他的信息:

这里有人在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' } } 

任何更新的最终版本应该用来代替。