如何使用Spring Data REST进行高级搜索?

2022-09-01 17:18:47

我的任务是使用Spring Data REST进行高级搜索。我该如何实现它?

我设法做了一个简单的搜索方法,就像这样:

public interface ExampleRepository extends CrudRepository<Example, UUID>{

    @RestResource(path="searchByName", rel="searchByName")
    Example findByExampleName(@Param("example") String exampleName);

}

如果我必须简单地转到url,这个例子可以完美地工作:

.../api/examples/search/searchByName?example=myExample

但是,如果要搜索多个字段,我该怎么办?

例如,如果我的 Example 类有 5 个字段,那么我应该使用什么实现来对所有可能的字段进行高级搜索?

考虑一下这个:

.../api/examples/search/searchByName?filed1=value1&field2=value2&field4=value4

和这个:

.../api/examples/search/searchByName?filed1=value1&field3=value3

我必须做些什么才能以适当的方式实现此搜索?

谢谢。


答案 1

Spring Data Rest已将QueryDSL与Web支持集成在一起,您可以将其用于高级搜索要求。您需要更改存储库以实施,事情将开箱即用。QueryDslPredicateExecutor

下面是有关该功能的博客文章中的示例:

$ http :8080/api/stores?address.city=York    
{
    "_embedded": {
        "stores": [
            {
                "_links": {
                    …
                }, 
                "address": {
                    "city": "New York", 
                    "location": { "x": -73.938421, "y": 40.851 }, 
                    "street": "803 W 181st St", 
                    "zip": "10033-4516"
                }, 
                "name": "Washington Hgts/181st St"
            }, 
            {
                "_links": {
                    …
                }, 
                "address": {
                    "city": "New York", 
                    "location": { "x": -73.939822, "y": 40.84135 }, 
                    "street": "4001 Broadway", 
                    "zip": "10032-1508"
                }, 
                "name": "168th & Broadway"
            }, 
            …
        ]
    }, 
    "_links": {
        …
    }, 
    "page": {
        "number": 0, 
        "size": 20, 
        "totalElements": 209, 
        "totalPages": 11
    }
}

答案 2

我设法使用示例查询来实现这一点。

假设您有以下模型:

@Entity
public class Company {

  @Id
  @GeneratedValue
  Long id;

  String name;
  String address;

  @ManyToOne
  Department department;

}


@Entity
public class Department {

  @Id
  @GeneratedValue
  Long id;

  String name;

}

和存储库:

@RepositoryRestResource
public interface CompanyRepository extends JpaRepository<Company, Long> {
}

(请注意,JpaRepository 实现了 QueryByExampleExecutor)。

现在,实现自定义控制器:

@RepositoryRestController
@RequiredArgsConstructor
public class CompanyCustomController {

  private final CompanyRepository repository;

  @GetMapping("/companies/filter")
  public ResponseEntity<?> filter(
      Company company,
      Pageable page,
      PagedResourcesAssembler assembler,
      PersistentEntityResourceAssembler entityAssembler
  ){

    ExampleMatcher matcher = ExampleMatcher.matching()
        .withIgnoreCase()
        .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);

    Example example = Example.of(company, matcher);

    Page<?> result = this.repository.findAll(example, page);

    return ResponseEntity.ok(assembler.toResource(result, entityAssembler));

  }
}

然后,您可以进行如下查询:

localhost:8080/companies/filter?name=google&address=NY

您甚至可以查询嵌套实体,例如:

localhost:8080/companies/filter?name=google&department.name=finances

为了简洁起见,我省略了一些细节,但我在Github上创建了一个工作示例


推荐