【问题标题】:Spring Data Neo4j - ORDER BY {order} failsSpring Data Neo4j - ORDER BY {order} 失败
【发布时间】:2017-01-16 11:53:26
【问题描述】:

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

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

我在这里错过了什么?

【问题讨论】:

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


    【解决方案1】:

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

    不能绑定的地方不能绑定:

    您不能将参数绑定到未设置为“参数绑定”的查询语法元素中。参数绑定不做简单的字符串替换(因为你可能会受到注入攻击),而是使用绑定 API 来绑定参数。您正在处理查询注释,就像它正在执行字符串替换一样,这不是正在发生的事情。

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

    • 代替字符串文字
    • 代替正则表达式
    • 字符串模式匹配
    • 使用属性创建节点,作为属性
    • 使用属性创建多个节点,作为属性
    • 设置节点的所有属性
    • 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 Data 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'
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多