Perpustakaan untuk membuat dan menjalankan kueri tingkat lanjut dan dinamis menggunakan JPA di Spring Boot.
Map<String, String>
, untuk mendukung titik akhir GET dengan parameter kueri.Melalui jpa-search-helper pengontrol Anda* akan dapat menerima permintaan seperti ini:
Modus 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 '
Modus 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 '
..bagaimana kamu melakukannya? Baca baca ini!
* Harap dicatat: perpustakaan tidak mengekspos pengontrol/Titik Akhir HTTP, tetapi hanya menawarkan repositori yang akan membangun dan mengeksekusi kueri.
Pembantu Pencarian JPA | Sepatu Musim Semi | Jawa |
---|---|---|
[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 - terbaru] | 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
Mulailah dengan menerapkan anotasi @Searchable
ke bidang di Model Domain Anda, atau entitas JPA Anda, yang ingin Anda sediakan untuk pencarian . Jika Anda memiliki bidang yang ingin Anda cari di dalam objek lain, beri anotasi dengan @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 ;
}
}
Anotasi memungkinkan Anda menentukan:
Properti inti:
entityFieldKey
: nama bidang yang ditentukan pada kacang entitas (tidak ditentukan jika menggunakan anotasi pada kacang entitas). Jika tidak ditentukan, kuncinya adalah nama bidang.
targetType
: jenis objek yang dikelola berdasarkan entitas. Jika tidak ditentukan, perpustakaan akan mencoba mendapatkannya berdasarkan tipe bidang (misalnya bidang Integer tanpa definisi tipe target akan menjadi INTEGER
). Jika tidak ada tipe yang kompatibel dengan tipe yang dikelola, maka akan dikelola sebagai string. Jenis yang dikelola:
STRING
, INTEGER
, DOUBLE
, FLOAT
, LONG
, BIGDECIMAL
, BOOLEAN
, DATE
, LOCALDATE
, LOCALDATETIME
, LOCALTIME
, OFFSETDATETIME
, OFFSETTIME
, ZONEDDATETIME
.Properti validasi:
datePattern
: hanya untuk jenis target DATE
, LOCALDATE
, LOCALDATETIME
, LOCALTIME
, OFFSETDATETIME
, OFFSETTIME
, ZONEDDATETIME
. Menentukan pola tanggal yang akan digunakan.maxSize, minSize
: panjang nilai maksimum/minimum.maxDigits, minDigits
: hanya untuk tipe numerik. Jumlah digit maksimum/minimum.regexPattern
: pola regex.decimalFormat
: hanya untuk tipe numerik desimal. Bawaan #.##
Lainnya:
sortable
: jika salah, kolom dapat digunakan untuk pencarian tetapi tidak dapat digunakan untuk pengurutan. Bawaan: benar.trim
: terapkan trim.tags
: berguna jika bidang Model Domain dapat berhubungan dengan beberapa bidang entitas (contohnya tersedia di bagian bawah).allowedFilters
: filter yang diizinkan secara eksklusif.notAllowedFilters
: filter tidak diperbolehkan.likeFilters
: diperbolehkan seperti filter ( berisi , dimulaiDengan , berakhirDengan ). Bawaan: benar.Melanjutkan contoh, kelas entitas kita:
@ 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
Repositori Spring JPA Anda harus memperluas JPASearchRepository<YourEntityClass>
.
@ Repository
public interface PersonRepository extends JpaRepository < PersonEntity , Long >, JPASearchRepository < PersonEntity > {
}
Di manajer Anda, atau di layanan Anda, atau di mana pun Anda ingin menggunakan repositori:
Mode 1 : tentukan peta <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 );
// ...
}
// ...
Mode 2 : alih-alih menggunakan peta, Anda perlu menggunakan JPASearchInput
, yang ditampilkan di sini, untuk kesederhanaan, dalam format 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
}
}
Melalui Mode 2 dimungkinkan untuk mengelola filter kompleks dengan AND
, OR
, dan NOT
(lihat nanti).
InvalidFieldException
.InvalidValueException
.JPASearchException
Nama penyaring | Kunci Perpustakaan | Mode yang didukung |
---|---|---|
DAN | Dan | 1, 2 |
ATAU | atau | 2 |
BUKAN | bukan | 2 |
Melalui Mode 1 , semua filter secara eksklusif menyusun pencarian AND
.
Untuk menggunakan operator lain, OR
dan NOT
, Anda harus menggunakan Mode 2
Nama penyaring | Kunci Perpustakaan | SQL | Mode yang didukung | Nilai diperlukan |
---|---|---|---|---|
Setara | persamaan | sql_col = val | 1,2 | Ya |
Berisi | berisi | sql_col SEPERTI '%val%' | 1,2 | Ya |
Di dalam | di dalam | sql_col IN (val1, val2, ..., valN) | 1,2 | Ya |
Dimulai dengan | dimulai dengan | sql_col SEPERTI 'val%' | 1,2 | Ya |
Berakhir Dengan | berakhirDengan | sql_col SEPERTI '%val' | 1,2 | Ya |
Lebih Besar Dari | gt | sql_col > val | 1,2 | Ya |
Lebih Besar Dari atau Sama | gte | sql_col >= val | 1,2 | Ya |
Kurang dari | lt | sql_col < val | 1,2 | Ya |
Kurang dari atau Sama | lte | sql_col <= val | 1,2 | Ya |
Di antara | di antara | sql_col ANTARA val1 DAN val2 | 1,2 | Ya |
Batal | batal | sql_col ADALAH BATAL | 1,2 | TIDAK |
Kosong | kosong | sql_collection_col ADALAH BATAL | 1,2 | TIDAK |
Modus 1
Deskripsi opsi | Kunci Perpustakaan |
---|---|
Abaikan kasus | #Saya |
Penyangkalan | #N |
Memangkas | #T |
Kunci opsi harus ditambahkan ke filter; misalnya ?firstName_eq#i=Biagio atau ?firstName_eq#i#n=Biagio
Modus 2
Deskripsi opsi | Kunci Perpustakaan (atribut Java) |
---|---|
Abaikan kasus | abaikan Kasus |
Penyangkalan | meniadakan |
Memangkas | memangkas |
Untuk setiap filter dimungkinkan untuk menentukan options
{
// ...
{
"operator" : " eq " ,
"key" : " firstName " ,
"value" : " Biagio " ,
"options" : {
"ignoreCase" : true ,
"trim" : false ,
"negate" : true
}
}
// ...
}
Objek Jawa:
@ Data
public static class JPASearchFilterOptions {
private boolean ignoreCase ;
private boolean trim ;
private boolean negate ;
}
Nama penyaring | Kunci | Nilai tetap |
---|---|---|
Batas (ukuran halaman) | membatasi | |
Offset (nomor halaman) | mengimbangi | |
Menyortir | menyortir | ASC, DESC |
Mode 1 : misalnya ?firstName_sort=DESC&_limit=10&_offset=0
Mode 2 : nilai options
root :
{
"filter" : {
// ...
},
"options" : {
"sortKey" : " firstName " ,
"sortDesc" : true ,
"pageSize" : 10 ,
"pageOffset" : 1
}
}
Objek Jawa:
@ Data
public static class JPASearchOptions {
private String sortKey ;
private Boolean sortDesc = false ;
private Integer pageSize ;
private Integer pageOffset ;
private List < String > selections ;
}
,
: misalnya ?myField_in=test1,test2 --> nilai yang dicari: [" test1 ", " test2 "]/,
: misalnya ?myField_in=test1,test2/,test3 --> nilai yang akan dicari: [" test1 ", " test2,test3 "] @Projectable
Mulailah dengan menerapkan anotasi @Projectable
ke bidang di Model Domain Anda, atau entitas JPA Anda, yang ingin Anda sediakan untuk dipilih . Jika Anda memiliki bidang yang ingin Anda pilih di dalam objek lain, beri anotasi dengan @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 ;
}
}
Anotasi memungkinkan Anda menentukan:
Properti inti:
entityFieldKey
: nama bidang yang ditentukan pada kacang entitas (tidak ditentukan jika menggunakan anotasi pada kacang entitas). Jika tidak ditentukan, kuncinya adalah nama bidang.JPASearchRepository
Repositori Spring JPA Anda harus memperluas JPAProjectionRepository<YourEntityClass>
.
@ Repository
public interface PersonRepository extends JpaRepository < PersonEntity , Long >, JPASearchRepository < PersonEntity >, JPAProjectionRepository < PersonEntity > {
}
Di manajer Anda, atau di layanan Anda, atau di mana pun Anda ingin menggunakan repositori:
Mode 1 : menentukan (atau menambahkan ke peta yang digunakan untuk pencarian Mode 1) peta:
,
// ...
@ 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
}
// ...
Mode 2 : alih-alih menggunakan peta, Anda perlu menggunakan JPASearchInput
, yang ditampilkan di sini, untuk kesederhanaan, dalam format 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 "
]
}
}
Untuk kedua mode, proyeksi akan mengembalikan hasil List<Map<String, Object>> dengan struktur peta dan kunci akan mencerminkan struktur entitas (agar jelas toJson(entityList) == toJson(mapList) )
Catatan 1:
Hati-hati: proyeksi default memaksa semua hubungan Gabung sebagai LEFT JOIN. Jika Anda tidak menginginkan perilaku ini, pilih untuk menggunakan metode repositori (metode dengan akhiran 'Klasik') yang memungkinkan Anda untuk memodifikasi hanya relasi yang ingin Anda modifikasi
Catatan 2:
Proyeksi, terlepas dari apakah Anda menginginkannya atau tidak, akan selalu mengekstrak bidang yang mewakili kunci utama suatu entitas (atau entitas terkait)
Catatan 3:
Penomoran halaman tidak didukung
InvalidFieldException
.JPASearchException
Dimungkinkan untuk memaksa gabungan dengan pengambilan untuk memungkinkan Hibernate (atau kerangka kerja JPA Anda) mengeksekusi satu kueri untuk hubungan yang ditentukan pada entitas. Ini hanya mungkin tanpa penomoran halaman :
// ...
Map < String , JoinFetch > fetches = Map . of ( "companyEntity" , JoinFetch . LEFT );
personRepository . findAll ( filters , Person . class , fetches );
// ...
Jika Anda memiliki Model Domain yang merupakan hasil konversi beberapa entitas, dimungkinkan untuk secara eksplisit menentukan peta (string, string) yang kuncinya mewakili nama bidang Model Domain dan nilainya adalah nama bidang tersebut. entitas yang akan dicari:
// ...
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 );
// ...
Kasus khusus lainnya adalah ketika suatu objek dapat diulangi dalam Model Domain untuk mewakili beberapa bagian entitas. Solusi untuk pencarian:
@ 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 '
Harap dicatat: perpustakaan ini tidak mengekspos titik akhir apa pun dan karenanya tidak ada pengontrol. Contoh proyek, lengkap dan lengkap, tersedia di sini.
Pengendali:
@ 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 );
}
}
Kacang Layanan/Manajer:
@ 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 ) {
// ...
}
}
Keriting:
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 '
atau
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 '
Pengendali:
@ 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 );
}
}
Kacang Layanan/Manajer:
@ 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 ) {
// ...
}
}
Keriting:
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 '
atau
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 '