Spring Data Neo4j 4中的分页和排序

10

在SDN4中,自定义查询是否支持分页?

  • 如果支持,它是如何工作的?
  • 如果不支持,有没有变通方法?

我有以下 Spring Data Neo4j 4 仓库:

@Repository
public interface TopicRepository 
  extends GraphRepository<Topic>,IAuthorityLookup {

  // other methods omitted
  @Query("MATCH (t:Topic)-[:HAS_OFFICER]->(u:User) "
    + "WHERE t.id = {0} "
    + "RETURN  u")
  public Page<User> topicOfficers(Long topicId, Pageable pageable);
}

相应的测试用例:

@Test
public void itShouldReturnAllOfficersAsAPage() {
  Pageable pageable = new PageRequest(1,10);
  Page<User> officers = topicRepository.topicOfficers(1L, pageable);
  assertNotNull(officers);
}

当我运行测试时,遇到了以下异常。
Failed to convert from type java.util.ArrayList<?> to type   org.springframework.data.domain.Page<?> for value '[org.lecture.model.User@1]'; 
nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type java.util.ArrayList<?> to type org.springframework.data.domain.Page<?>

这是我的设置:

dependencies {
//other dependencies omitted
  compile("org.neo4j:neo4j-cypher-dsl:2.0.1")


  compile "org.neo4j.app:neo4j-server:2.2.2"

  compile(group: 'org.springframework.data',
          name: 'spring-data-neo4j',
          version: '4.0.0.BUILD-SNAPSHOT')


  compile(group: 'org.springframework.data',
          name: 'spring-data-neo4j',
          version: '4.0.0.BUILD-SNAPSHOT',
          classifier: 'tests')

  testCompile(group: 'org.neo4j',
          name: 'neo4j-kernel',
          version: '2.2.2',
          classifier: 'tests')

  testCompile(group: 'org.neo4j.app',
              name: 'neo4j-server',
              version: '2.2.2',
              classifier: 'tests')

  testCompile(group: 'org.neo4j',
              name: 'neo4j-io',
              version: '2.2.2',
              classifier: 'tests')
} 

我使用的快照应该能够处理分页,因为以下测试运行良好:
@Test
public void itShouldReturnAllTopicsAsAPage() {

  Pageable pageable = new PageRequest(1,10);
  Page<Topic> topics = topicRepository.findAll(pageable);

  assertNotNull(topics);
}
3个回答

6
现在可以使用查询中的SortPageable接口来进行此操作,此问题已在DATAGRAPH-653中得到修复,并标记为版本4.2.0.M1(目前处于预发布状态)。以下查询是可能的:
@Query("MATCH (movie:Movie {title={0}})<-[:ACTS_IN]-(actor) RETURN actor")
List<Actor> getActorsThatActInMovieFromTitle(String movieTitle, Sort sort);

并且:

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

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

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

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


4
目前这是不可能的。
要启用此功能,我们需要执行几个步骤。首先,在启动时,我们需要检查查询关联的方法签名,并将查询标记为需要分页。然后,在运行时当调用该方法时,我们需要获取可分页实例,提取页面参数并将它们作为SKIP和LIMIT子句应用于相关的Cypher查询。最后,在返回时,我们需要将结果包装在一个Page对象中。所以需要做一些工作才能启用此功能。
同时,您可以尝试使用参数化值向查询添加SKIP和LIMIT子句,并通过查询方法传递相应的值。我没有尝试过,但理论上应该可以。
  @Query("MATCH (t:Topic)-[:HAS_OFFICER]->(u:User) "
+ "WHERE t.id = {0} "
+ "RETURN  u SKIP {1} LIMIT {2}" )
public List<User> topicOfficers(long topicId, long skip, long limit)

谢谢您的回复!我有一个问题,因为您对SDN4比我更了解...这是一个功能(如果有的话)在可预见的未来会提供吗?比如说,SDN4的RC版本。这些信息将帮助我决定是否重写我的API。 - ShrimpPhaser
因为现在处于代码冻结状态,所以它不会出现在第一个RC中。我已经为此创建了一个工单,并将其添加到下一个版本的待办事项列表中。目前我无法确定那个版本何时发布。 https://jira.spring.io/browse/DATAGRAPH-653 - Vince
@Vince 对于我们的系统,我们需要从执行自定义分页查询返回的Page中获取getTotalPages()、isFirst()和isLast()的值。您能否提供关于如何实现这一点的建议?或者是否有SDN代码可以指导我构建Page对象?谢谢 - Coder Shark
请查看我的答案:http://stackoverflow.com/questions/32011358/sdn4-custom-query-pagination-alternative-for-page-contents/32013946#32013946 - Vince
我刚刚通过在 @Query 注释中添加 countQuery 解决了这个问题。示例:@Query(value = "MATCH (t:Topic)-[:HAS_OFFICER]->(u:User) WHERE t.id = {0} RETURN u", countQuery = "MATCH (t:Topic)-[:HAS_OFFICER]->(u:User) WHERE t.id = {0} RETURN count(u)") - Marian

1
作为对@Jayson Minard答案的跟进,更近期的Spring Data Neo4j版本(6.0.7+)要求在常规查询中附加一个计数查询以返回Page对象,例如:

@Query(value = "MATCH (t:Topic)-[:HAS_OFFICER]->(u:User) WHERE t.id = {0} "
             + "RETURN u SKIP $skip LIMIT $limit",
        countQuery = "MATCH (t:Topic)-[:HAS_OFFICER]->(u:User) WHERE t.id = {0} "
             + "RETURN count(u)")
public Page<User> topicOfficers(Long topicId, Pageable pageable);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接