Spring Boot에서 JPA를 사용하여 고급 및 동적 쿼리를 구축하고 실행하기 위한 라이브러리입니다.
Map<String, String>
통해 쿼리 매개변수가 있는 GET 엔드포인트를 지원합니다.jpa-search-helper를 통해 컨트롤러*는 다음과 같은 요청을 받을 수 있습니다.
모드 1 :
curl -X GET
' https://myexampledomain.com/persons?
firstName=Biagio
&lastName_startsWith=Toz
&birthDate_gte=19910101
&country_in=IT,FR,DE
&address_eq=Via Roma 1,Via Milano/,1,20 West/,34th Street
&company.name_in=Microsoft,Apple,Google
&company.employees_between=500,5000 '
모드 2 :
curl -X POST -H " Content-type: application/json " -d ' {
"filter" : {
"operator": "and", // the first filter must contain a root operator: AND, OR or NOT
"filters" : [
{
"operator": "eq",
"key": "firstName",
"value": "Biagio"
},
{
"operator": "or",
"filters": [
{
"operator": "startsWith",
"key": "lastName",
"value": "Toz",
"options": {
"ignoreCase": true
}
},
{
"operator": "endsWith",
"key": "lastName",
"value": "ZZI",
"options": {
"ignoreCase": true,
"trim" : true
}
}
]
},
{
"operator": "in",
"key": "company.name",
"values": ["Microsoft", "Apple", "Google"]
},
{
"operator": "or",
"filters": [
{
"operator": "gte",
"key": "birthDate",
"value": "19910101"
},
{
"operator": "lte",
"key": "birthDate",
"value": "20010101"
}
]
},
{
"operator": "between",
"key" : "company.employees",
"values": [500, 5000],
"options": {
"negate": true
}
}
]
},
"options": {
"pageSize": 10,
"pageOffset": 0,
"sortKey": "birthDate",
"sortDesc": false
}
} ' ' https://myexampledomain.com/persons '
..어떻게 하시나요? 이 읽어보기를 읽어보세요!
* 참고: 라이브러리는 컨트롤러/HTTP 끝점을 노출하지 않지만 쿼리를 구축하고 실행할 저장소만 제공합니다.
JPA 검색 도우미 | 스프링 부트 | 자바 |
---|---|---|
[v0.0.1 - v2.1.1] | 3.2.x | [17~23] |
[v3.0.0 - v3.2.2] | 3.3.x | [17~23] |
[v3.3.0 - 최신] | 3.4.x | [17~23] |
<dependency>
<groupId>app.tozzi</groupId>
<artifactId>jpa-search-helper</artifactId>
<version>3.3.0</version>
</dependency>
implementation 'app.tozzi:jpa-search-helper:3.3.0
@Searchable
주석 검색에 사용할 수 있게 하려는 도메인 모델 또는 JPA 엔터티의 필드에 @Searchable
주석을 적용하는 것부터 시작하세요. 다른 객체 내에서 검색 가능하게 만들고 싶은 필드가 있는 경우 @NestedSearchable
주석을 추가하세요.
@ Data
public class Person {
@ Searchable
private String firstName ;
@ Searchable
private String lastName ;
@ Searchable ( entityFieldKey = "dateOfBirth" )
private Date birthDate ;
@ Searchable
private String country ;
@ Searchable
private String fillerOne ;
@ Searchable
private String fillerTwo ;
@ NestedSearchable
private Company company ;
@ Data
public static class Company {
@ Searchable ( entityFieldKey = "companyEntity.name" )
private String name ;
@ Searchable ( entityFieldKey = "companyEntity.employeesCount" )
private int employees ;
}
}
주석을 사용하면 다음을 지정할 수 있습니다.
핵심 속성:
entityFieldKey
: 엔터티 빈에 정의된 필드의 이름입니다(엔티티 빈에 주석을 사용하는 경우 지정되지 않음). 지정하지 않으면 키는 필드 이름이 됩니다.
targetType
: 엔터티별 관리 개체 유형입니다. 지정하지 않으면 라이브러리는 필드 유형을 기반으로 이를 얻으려고 시도합니다(예: 대상 유형 정의가 없는 정수 필드는 INTEGER
가 됩니다). 관리되는 타입과 호환되는 타입이 없을 경우 문자열로 관리됩니다. 관리형 유형:
STRING
, INTEGER
, DOUBLE
, FLOAT
, LONG
, BIGDECIMAL
, BOOLEAN
, DATE
, LOCALDATE
, LOCALDATETIME
, LOCALTIME
, OFFSETDATETIME
, OFFSETTIME
, ZONEDDATETIME
.유효성 검사 속성:
datePattern
: DATE
, LOCALDATE
, LOCALDATETIME
, LOCALTIME
, OFFSETDATETIME
, OFFSETTIME
, ZONEDDATETIME
대상 유형에만 해당됩니다. 사용할 날짜 패턴을 정의합니다.maxSize, minSize
: 값의 최대/최소 길이.maxDigits, minDigits
: 숫자 유형에만 해당됩니다. 최대/최소 자릿수입니다.regexPattern
: 정규식 패턴입니다.decimalFormat
: 십진수 유형에만 해당됩니다. 기본 #.##
다른:
sortable
: false인 경우 필드를 검색에 사용할 수 있지만 정렬에는 사용할 수 없습니다. 기본값: 참.trim
: 트림을 적용합니다.tags
: 도메인 모델 필드가 여러 엔터티 필드에 해당할 수 있는 경우 유용합니다(예제는 아래에서 더 자세히 볼 수 있음).allowedFilters
: 독점적으로 허용되는 필터입니다.notAllowedFilters
: 허용되지 않는 필터입니다.likeFilters
: 유사 필터( contain , startWith , endWith )가 허용됩니다. 기본값: 참.예제를 계속하면 엔터티 클래스는 다음과 같습니다.
@ Entity
@ Data
public class PersonEntity {
@ Id
private Long id ;
@ Column ( name = "FIRST_NAME" )
private String firstName ;
@ Column ( name = "LAST_NAME" )
private String lastName ;
@ Column ( name = "BIRTH_DATE" )
private Date dateOfBirth ;
@ Column ( name = "COUNTRY" )
private String country ;
@ Column ( name = "FIL_ONE" )
private String fillerOne ;
@ Column ( name = "FIL_TWO" )
private String fillerTwo ;
@ OneToOne
private CompanyEntity companyEntity ;
}
@ Entity
@ Data
public class CompanyEntity {
@ Id
private Long id ;
@ Column ( name = "NAME" )
private String name ;
@ Column ( name = "COUNT" )
private Integer employeesCount ;
}
JPASearchRepository
인터페이스 Spring JPA 저장소는 JPASearchRepository<YourEntityClass>
확장해야 합니다.
@ Repository
public interface PersonRepository extends JpaRepository < PersonEntity , Long >, JPASearchRepository < PersonEntity > {
}
관리자, 서비스 또는 저장소를 사용하려는 모든 곳에서:
모드 1 : <filter_key#options, value> 맵 정의:
// ...
@ Autowired
private PersonRepository personRepository ;
public List < Person > advancedSearch () {
// Pure example, in real use case it is expected that these filters can be passed directly by the controller
Map < String , String > filters = new HashMap <>();
filters . put ( "firstName_eq" , "Biagio" );
filters . put ( "lastName_startsWith#i" , "Toz" ); // ignore case
filters . put ( "birthDate_gte" , "19910101" );
filters . put ( "country_in" , "IT,FR,DE" );
filters . put ( "company.name_eq#n" , "Bad Company" ); // negation
filters . put ( "company.employees_between" , "500,5000" );
filters . put ( "fillerOne_null#n" , "true" ); // not null
filters . put ( "fillerTwo_empty" , "true" ); // empty
// Without pagination
List < PersonEntity > fullSearch = personRepository . findAll ( filters , Person . class );
filters . put ( "birthDate_sort" : "ASC" ); // sorting key and sorting order
filters . put ( "_limit" , "10" ); // page size
filters . put ( "_offset" , "0" ); // page offset
// With pagination
Page < PersonEntity > sortedAndPaginatedSearch = personRepository . findAllWithPaginationAndSorting ( filters , Person . class );
// ...
}
// ...
모드 2 : 맵 대신 여기에 표시된 JPASearchInput
단순화하기 위해 JSON 형식으로 사용해야 합니다.
{
"filter" : {
"operator" : " and " , // the first filter must contain a root operator: AND, OR or NOT
"filters" : [
{
"operator" : " eq " ,
"key" : " firstName " ,
"value" : " Biagio "
},
{
"operator" : " or " ,
"filters" : [
{
"operator" : " startsWith " ,
"key" : " lastName " ,
"value" : " Toz " ,
"options" : {
"ignoreCase" : true
}
},
{
"operator" : " endsWith " ,
"key" : " lastName " ,
"value" : " ZZI " ,
"options" : {
"ignoreCase" : true ,
"trim" : true
}
}
]
},
{
"operator" : " in " ,
"key" : " company.name " ,
"values" : [ " Microsoft " , " Apple " , " Google " ]
},
{
"operator" : " or " ,
"filters" : [
{
"operator" : " gte " ,
"key" : " birthDate " ,
"value" : " 19910101 "
},
{
"operator" : " lte " ,
"key" : " birthDate " ,
"value" : " 20010101 "
}
]
},
{
"operator" : " empty " ,
"key" : " fillerOne " ,
"options" : {
"negate" : true
}
},
{
"operator" : " between " ,
"key" : " company.employees " ,
"values" : [ 500 , 5000 ],
"options" : {
"negate" : true
}
}
]
},
"options" : {
"pageSize" : 10 ,
"pageOffset" : 0 ,
"sortKey" : " birthDate " ,
"sortDesc" : false
}
}
모드 2를 통해 AND
, OR
및 NOT
사용하여 복잡한 필터를 관리할 수 있습니다(나중에 참조).
InvalidFieldException
을 받게 됩니다.InvalidValueException
이 발생합니다.JPASearchException
필터 이름 | 도서관 열쇠 | 지원되는 모드 |
---|---|---|
그리고 | 그리고 | 1, 2 |
또는 | 또는 | 2 |
아니다 | ~ 아니다 | 2 |
모드 1을 통해 모든 필터는 독점적으로 AND
검색을 구성합니다.
다른 연산자인 OR
및 NOT
사용하려면 모드 2를 사용해야 합니다.
필터 이름 | 도서관 열쇠 | SQL | 지원되는 모드 | 필수 값 |
---|---|---|---|---|
같음 | eq | sql_col = 발 | 1,2 | 예 |
포함 | 포함 | sql_col LIKE '%val%' | 1,2 | 예 |
~ 안에 | ~에 | sql_col IN(val1, val2, ..., valN) | 1,2 | 예 |
다음으로 시작 | 시작 | sql_col LIKE '발%' | 1,2 | 예 |
다음으로 끝남 | 다음으로 끝남 | sql_col LIKE '%val' | 1,2 | 예 |
보다 큼 | gt | sql_col > 발 | 1,2 | 예 |
보다 크거나 같음 | gte | sql_col >= 발 | 1,2 | 예 |
미만 | lt | sql_col < 발 | 1,2 | 예 |
작거나 같음 | LTE | sql_col <= 발 | 1,2 | 예 |
사이 | ~ 사이 | val1과 val2 사이의 sql_col | 1,2 | 예 |
널 | null | sql_col은 NULL입니다. | 1,2 | 아니요 |
비어 있는 | 비어 있는 | sql_collection_col은 NULL입니다. | 1,2 | 아니요 |
모드 1
옵션 설명 | 도서관 열쇠 |
---|---|
대소문자 무시 | #나 |
부정 | #N |
손질 | #티 |
옵션 키는 필터에 추가되어야 합니다. 예: ?firstName_eq#i=Biagio 또는 ?firstName_eq#i#n=Biagio
모드 2
옵션 설명 | 라이브러리 키(Java 속성) |
---|---|
대소문자 무시 | 대소문자 무시 |
부정 | 부정하다 |
손질 | 손질 |
각 필터에 대해 options
정의할 수 있습니다.
{
// ...
{
"operator" : " eq " ,
"key" : " firstName " ,
"value" : " Biagio " ,
"options" : {
"ignoreCase" : true ,
"trim" : false ,
"negate" : true
}
}
// ...
}
자바 객체:
@ Data
public static class JPASearchFilterOptions {
private boolean ignoreCase ;
private boolean trim ;
private boolean negate ;
}
필터 이름 | 열쇠 | 고정값 |
---|---|---|
제한(페이지 크기) | 한계 | |
오프셋(페이지 번호) | 오프셋 | |
종류 | 종류 | 오름차순, 내림차순 |
모드 1 : 예 : ?firstName_sort=DESC&_limit=10&_offset=0
모드 2 : 값 루트 options
:
{
"filter" : {
// ...
},
"options" : {
"sortKey" : " firstName " ,
"sortDesc" : true ,
"pageSize" : 10 ,
"pageOffset" : 1
}
}
자바 객체:
@ Data
public static class JPASearchOptions {
private String sortKey ;
private Boolean sortDesc = false ;
private Integer pageSize ;
private Integer pageOffset ;
private List < String > selections ;
}
,
: 예 : ?myField_in=test1,test2 --> 검색할 값: [" test1 ", " test2 "]/,
: 예 : ?myField_in=test1,test2/,test3 --> 검색할 값: [" test1 ", " test2,test3 "] @Projectable
주석 도메인 모델 또는 JPA 엔터티에서 선택할 수 있는 필드에 @Projectable
주석을 적용하는 것부터 시작하세요. 다른 객체 내에서 선택 가능하게 만들고 싶은 필드가 있는 경우 @NestedProjectable
주석을 추가하세요.
@ Data
public class Person {
@ Searchable
private String firstName ;
@ Projectable
@ Searchable
private String lastName ;
@ Projectable ( entityFieldKey = "dateOfBirth" )
@ Searchable ( entityFieldKey = "dateOfBirth" )
private Date birthDate ;
@ Searchable
private String country ;
@ Searchable
private String fillerOne ;
@ Searchable
private String fillerTwo ;
@ NestedProjectable
@ NestedSearchable
private Company company ;
@ Data
public static class Company {
@ Searchable ( entityFieldKey = "companyEntity.name" )
private String name ;
@ Projectable ( entityFieldKey = "companyEntity.employeesCount" )
@ Searchable ( entityFieldKey = "companyEntity.employeesCount" )
private int employees ;
}
}
주석을 사용하면 다음을 지정할 수 있습니다.
핵심 속성:
entityFieldKey
: 엔터티 빈에 정의된 필드의 이름(엔티티 빈에 주석을 사용하는 경우 지정되지 않음) 지정하지 않으면 키는 필드 이름이 됩니다.JPASearchRepository
인터페이스 Spring JPA 저장소는 JPAProjectionRepository<YourEntityClass>
확장해야 합니다.
@ Repository
public interface PersonRepository extends JpaRepository < PersonEntity , Long >, JPASearchRepository < PersonEntity >, JPAProjectionRepository < PersonEntity > {
}
관리자, 서비스 또는 저장소를 사용하려는 모든 곳에서:
모드 1 : 지도를 정의(또는 모드 1 검색에 사용되는 지도에 추가):
,
// ...
@ Autowired
private PersonRepository personRepository ;
public List < Person > advancedSearch () {
// Pure example, in real use case it is expected that these filters can be passed directly by the controller
Map < String , String > filters = new HashMap <>();
filters . put ( "firstName_eq" , "Biagio" );
filters . put ( "lastName_startsWith#i" , "Toz" ); // ignore case
filters . put ( "birthDate_gte" , "19910101" );
filters . put ( "country_in" , "IT,FR,DE" );
filters . put ( "company.name_eq#n" , "Bad Company" ); // negation
filters . put ( "company.employees_between" , "500,5000" );
filters . put ( "fillerOne_null#n" , "true" ); // not null
filters . put ( "fillerTwo_empty" , "true" ); // empty
// Selections
filters . put ( "selections" , "lastName,birthDate,company.employees" );
// Without sorting
List < Map < String , Object >> result = personRepository . projection ( filters , Person . class , PersonEntity . class );
filters . put ( "birthDate_sort" : "ASC" ); // sorting key and sorting order
// With sorting
List < Map < String , Object >> sortedAndPaginatedSearch = personRepository . projectionWithSorting ( filters , Person . class , PersonEntity . class );
// ... convert the list of maps into your model
}
// ...
모드 2 : 맵 대신 여기에 표시된 JPASearchInput
단순화하기 위해 JSON 형식으로 사용해야 합니다.
{
"filter" : {
"operator" : " and " , // the first filter must contain a root operator: AND, OR or NOT
"filters" : [
{
"operator" : " eq " ,
"key" : " firstName " ,
"value" : " Biagio "
},
{
"operator" : " or " ,
"filters" : [
{
"operator" : " startsWith " ,
"key" : " lastName " ,
"value" : " Toz " ,
"options" : {
"ignoreCase" : true
}
},
{
"operator" : " endsWith " ,
"key" : " lastName " ,
"value" : " ZZI " ,
"options" : {
"ignoreCase" : true ,
"trim" : true
}
}
]
},
{
"operator" : " in " ,
"key" : " company.name " ,
"values" : [ " Microsoft " , " Apple " , " Google " ]
},
{
"operator" : " or " ,
"filters" : [
{
"operator" : " gte " ,
"key" : " birthDate " ,
"value" : " 19910101 "
},
{
"operator" : " lte " ,
"key" : " birthDate " ,
"value" : " 20010101 "
}
]
},
{
"operator" : " empty " ,
"key" : " fillerOne " ,
"options" : {
"negate" : true
}
},
{
"operator" : " between " ,
"key" : " company.employees " ,
"values" : [ 500 , 5000 ],
"options" : {
"negate" : true
}
}
]
},
"options" : {
"pageSize" : 10 ,
"pageOffset" : 0 ,
"sortKey" : " birthDate " ,
"sortDesc" : false ,
"selections" : [
" lastName " ,
" birthDate " ,
" company.employees "
]
}
}
두 모드 모두에서 프로젝션은 맵 구조와 키가 엔터티 구조를 반영하는 List<Map<String, Object>> 결과를 반환합니다(명확하게 말하면 toJson(entityList) == toJson(mapList) ).
참고 1:
주의하세요. 기본 프로젝션은 모든 Join 관계를 LEFT JOIN으로 강제합니다. 이 동작을 원하지 않으면 수정하려는 관계만 수정할 수 있는 저장소 방법('Classic' 접미사가 있는 방법)을 사용하도록 선택하십시오.
참고 2:
프로젝션은 원하는지 여부에 관계없이 항상 엔터티(또는 관련 엔터티)의 기본 키를 나타내는 필드를 추출합니다.
참고 3:
페이지 매김이 지원되지 않습니다
InvalidFieldException
을 받게 됩니다.JPASearchException
Hibernate(또는 JPA 프레임워크)가 엔터티에 정의된 관계에 대해 단일 쿼리를 실행하도록 허용하기 위해 가져오기를 사용하여 강제로 조인하는 것이 가능합니다. 이는 페이지 매김 없이만 가능합니다 .
// ...
Map < String , JoinFetch > fetches = Map . of ( "companyEntity" , JoinFetch . LEFT );
personRepository . findAll ( filters , Person . class , fetches );
// ...
여러 엔터티를 변환한 결과인 도메인 모델이 있는 경우 키가 도메인 모델 필드의 이름을 나타내고 값이 해당 필드의 이름인 맵(문자열, 문자열)을 명시적으로 지정할 수 있습니다. 검색할 엔터티:
// ...
Map < String , String > entityFieldMap = Map . of ( "company" , "companyEntity.name" );
// Without pagination
personRepository . findAll ( filters , Person . class , fetches , entityFieldMap );
// With pagination
personRepository . findAllWithPaginationAndSorting ( filters , Person . class , entityFieldMap );
// ...
또 다른 특별한 경우는 개체가 도메인 모델 내에서 반복되어 엔터티의 여러 부분을 나타낼 수 있는 경우입니다. 검색 솔루션:
@ Entity
public class CoupleEntity {
@ Id
private Long id ;
@ Column ( name = "p1_fn" )
private String p1FirstName ;
@ Column ( name = "p1_ln" )
private String p1LastName ;
@ Column ( name = "p2_fn" )
private String p2FirstName ;
@ Column ( name = "p2_ln" )
private String p2LastName ;
}
@ Data
public class Couple {
@ NestedSearchable
private Person p1 ;
@ NestedSearchable
private Person p2 ;
@ Data
public static class Person {
@ Searchable ( tags = {
@ Tag ( fieldKey = "p1.firstName" , entityFieldKey = "p1FirstName" ),
@ Tag ( fieldKey = "p2.firstName" , entityFieldKey = "p2FirstName" ),
})
private String firstName ;
@ Searchable ( tags = {
@ Tag ( fieldKey = "p1.lastName" , entityFieldKey = "p1LastName" ),
@ Tag ( fieldKey = "p2.lastName" , entityFieldKey = "p2LastName" ),
})
private String lastName ;
}
}
curl - request GET
- url ' https://www.myexampledomain.com/couples?
p1.firstName_iEq=Romeo
&p2.firstName_iEq=Giulietta '
참고: 이 라이브러리는 엔드포인트를 노출하지 않으므로 컨트롤러도 없습니다. 여기에서 철저하고 완전한 예제 프로젝트를 확인할 수 있습니다.
제어 장치:
@ RestController
@ RequestMapping ( "/persons" )
public class PersonController {
@ Autowired
private PersonManager personManager ;
@ GetMapping ( produces = MediaType . APPLICATION_JSON_VALUE )
public List < Person > findPersons ( @ RequestParam Map < String , String > requestParams ) {
return personManager . find ( requestParams );
}
@ GetMapping ( path = "/projection" , produces = MediaType . APPLICATION_JSON_VALUE )
public List < Person > projection ( @ RequestParam Map < String , String > requestParams ) {
return personManager . projection ( requestParams );
}
}
서비스/관리자 빈:
@ Service
public class PersonManager {
@ Autowired
private PersonRepository personRepository ;
public List < Person > find ( Map < String , String > filters ) {
return personRepository . findAllWithPaginationAndSorting ( filters , Person . class ). stream (). map ( this :: toModel ). toList ();
}
public List < Person > projection ( Map < String , String > filters ) {
return personRepository . projection ( filters , Person . class , PersonEntity . class ). stream (). map ( this :: toModel ). toList ();
}
private static Person toModel ( PersonEntity personEntity ) {
// ...
}
private static Person toModel ( Map < String , Object > entityMap ) {
// ...
}
}
컬:
curl - X GET
' http://localhost:8080/persons?
firstName=Biagio
&lastName_startsWith=Toz
&birthDate_gte=19910101
&country_in=IT,FR,DE
&company.name_in=Microsoft,Apple
&company.employees_between=500,5000 '
또는
curl - X GET
' http://localhost:8080/persons/projection?
firstName=Biagio
&lastName_startsWith=Toz
&birthDate_gte=19910101
&country_in=IT,FR,DE
&company.name_in=Microsoft,Apple
&company.employees_between=500,5000
&selections=firstName,birthDate '
제어 장치:
@ RestController
@ RequestMapping ( "/persons" )
@ Validated
public class PersonController {
@ Autowired
private PersonManager personManager ;
@ PostMapping ( produces = MediaType . APPLICATION_JSON_VALUE , consumes = MediaType . APPLICATION_JSON_VALUE )
public List < Person > findPersons ( @ Valid @ RequestBody JPASearchInput input ) {
return personManager . find ( input );
}
}
@ PostMapping ( path = "/projection" , produces = MediaType . APPLICATION_JSON_VALUE , consumes = MediaType . APPLICATION_JSON_VALUE )
public List < Person > projection ( @ Valid @ RequestBody JPASearchInput input ) {
return personManager . projection ( input );
}
}
서비스/관리자 빈:
@ Service
public class PersonManager {
@ Autowired
private PersonRepository personRepository ;
public List < Person > find ( JPASearchInput input ) {
return personRepository . findAllWithPaginationAndSorting ( input , Person . class ). stream (). map ( this :: toModel ). toList ();
}
public List < Person > find ( JPASearchInput input ) {
return personRepository . projection ( input , Person . class , PersonEntity . class ). stream (). map ( this :: toModel ). toList ();
}
private static Person toModel ( PersonEntity entity ) {
// ...
}
private static Person toModel ( Map < String , Object > entityMap ) {
// ...
}
}
컬:
curl -X POST -H " Content-type: application/json " -d ' {
"filter" : {
"operator": "and", // the first filter must contain a root operator: AND, OR or NOT
"filters" : [
{
"operator": "eq",
"key": "firstName",
"value": "Biagio"
},
{
"operator": "or",
"filters": [
{
"operator": "startsWith",
"key": "lastName",
"value": "Toz",
"options": {
"ignoreCase": true
}
},
{
"operator": "endsWith",
"key": "lastName",
"value": "ZZI",
"options": {
"ignoreCase": true,
"trim" : true
}
}
]
},
{
"operator": "in",
"key": "company.name",
"values": ["Microsoft", "Apple", "Google"]
},
{
"operator": "or",
"filters": [
{
"operator": "gte",
"key": "birthDate",
"value": "19910101"
},
{
"operator": "lte",
"key": "birthDate",
"value": "20010101"
}
]
},
{
"operator": "between",
"key" : "company.employees",
"values": [500, 5000],
"options": {
"negate": true
}
}
]
},
"options": {
"pageSize": 10,
"pageOffset": 0,
"sortKey": "birthDate",
"sortDesc": false
}
} ' ' http://localhost:8080/persons '
또는
curl -X POST -H " Content-type: application/json " -d ' {
"filter" : {
"operator": "and", // the first filter must contain a root operator: AND, OR or NOT
"filters" : [
{
"operator": "eq",
"key": "firstName",
"value": "Biagio"
},
{
"operator": "or",
"filters": [
{
"operator": "startsWith",
"key": "lastName",
"value": "Toz",
"options": {
"ignoreCase": true
}
},
{
"operator": "endsWith",
"key": "lastName",
"value": "ZZI",
"options": {
"ignoreCase": true,
"trim" : true
}
}
]
},
{
"operator": "in",
"key": "company.name",
"values": ["Microsoft", "Apple", "Google"]
},
{
"operator": "or",
"filters": [
{
"operator": "gte",
"key": "birthDate",
"value": "19910101"
},
{
"operator": "lte",
"key": "birthDate",
"value": "20010101"
}
]
},
{
"operator": "between",
"key" : "company.employees",
"values": [500, 5000],
"options": {
"negate": true
}
}
]
},
"options": {
"sortKey": "birthDate",
"sortDesc": false,
"selections" : [
"birthDate",
"firstName",
"lastName"
]
}
} ' ' http://localhost:8080/persons/projection '