Spring Data Neo4j - ORDER BY {order}失败

时间:2016-09-08 13:51:27

标签: spring-data cypher kotlin spring-data-neo4j-4

我有一个查询,其结果应该根据传递的参数进行排序:

@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,但这没有帮助。

我在这里缺少什么?

1 个答案:

答案 0 :(得分:3)

这是更改排序分页信息的错误模型。您可以跳到下面的答案来使用这些选项,或继续阅读以解释代码中的错误。

你不能绑定不允许绑定的地方:

您无法将参数绑定到未为&#34;参数绑定&#34;设置的查询的语法元素中。参数绑定不会进行简单的字符串替换(因为您将对注入攻击开放),而是使用绑定API来绑定参数。您正在处理查询注释,就像它正在执行字符串替换,而这不是正在发生的事情。

parameter binding docs for Neo4JJava manual for Query Parameters显示您可以绑定的确切位置,允许的唯一位置是:

  • 代替String Literals
  • 代替正则表达
  • 字符串模式匹配
  • 使用属性创建节点,作为属性
  • 使用属性创建多个节点,作为属性
  • 设置节点的所有属性
  • SKIP和LIMIT的数值
  • 作为节点ID
  • 作为多个节点ID
  • 指数值
  • 索引查询

在ORDER BY子句中没有任何内容可以说明您正在尝试的内容。

并不是说Spring Data的作者无法解决这个问题,并且允许在其他地方进行绑定,但是看起来他们做得比Neo4J Java API允许的更多。

您可以使用Sort类:

允许将其标记为版本4.2.0.M1的修复程序,截至2016年9月8日为预发布版,请参阅下文,了解使用里程碑版本

Spring Data有一个Sort class,如果你的@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 docs中,您会看到使用分页的示例:

@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
Page<Actor> getActorsThatActInMovieFromTitle(String movieTitle, PageRequest page);

来自Spring Data + Neo4j文档中Cypher Examples的示例

PageRequest class也允许排序参数化。任何实现Pageable的东西都会这样做。使用Pageable可能更合适:

@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
Page<Actor> getActorsThatActInMovieFromTitle(String movieTitle, Pageable page);

您可以在早期版本中使用SpEL:

作为替代方案,您可以查看using SpEL expressions以在查询的其他区域中进行替换。我不熟悉它,但它说:

  

由于此机制也公开了SortPageable等特殊参数类型,因此我们现在可以在本机查询中使用分页。

official docs似乎表示它更有限。

你应该知道其他信息:

以下是有人在GitHub issue报告您完全相同的问题。然后会导致DATAGRAPH-653问题,该问题在版本4.2.0.M1中标记为已修复。这引用了过时的其他SO问题,因此您应该忽略那些不再正确的Paging and sorting in Spring Data Neo4j 4

查找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'
    }
}

应该使用任何较新的最终版本。