Bibliothek zum Erstellen und Ausführen erweiterter und dynamischer Abfragen mithilfe von JPA in Spring Boot.
Map<String, String>
, um GET-Endpunkte mit Abfrageparametern zu unterstützen.Über jpa-search-helper kann Ihr Controller* Anfragen wie diese empfangen:
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 '
..wie machst du das? Lesen Sie diese Readme-Datei!
* Bitte beachten Sie: Die Bibliothek stellt keine Controller/HTTP-Endpunkte bereit, sondern bietet nur das Repository, das die Abfragen erstellt und ausführt.
JPA-Suchhelfer | Frühlingsstiefel | Java |
---|---|---|
[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 – aktuell] | 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
-Annotation Wenden Sie zunächst die Annotation @Searchable
auf die Felder in Ihrem Domänenmodell oder alternativ Ihrer JPA-Entität an, die Sie für die Suche verfügbar machen möchten . Wenn Sie Felder haben, die Sie in anderen Objekten durchsuchbar machen möchten, kommentieren Sie diese mit @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 ;
}
}
Mit der Anmerkung können Sie Folgendes angeben:
Kerneigenschaften:
entityFieldKey
: Der Name des im Entity-Bean definierten Felds (muss nicht angegeben werden, wenn die Annotation im Entity-Bean verwendet wird). Wenn nicht angegeben, ist der Schlüssel der Feldname.
targetType
: der verwaltete Objekttyp nach Entität. Wenn nicht angegeben, versucht die Bibliothek, es basierend auf dem Feldtyp abzurufen (z. B. ein Ganzzahlfeld ohne Zieltypdefinition ist INTEGER
). Wenn es keinen Typ gibt, der mit den verwalteten Typen kompatibel ist, wird er als Zeichenfolge verwaltet. Verwaltete Typen:
STRING
, INTEGER
, DOUBLE
, FLOAT
, LONG
, BIGDECIMAL
, BOOLEAN
, DATE
, LOCALDATE
, LOCALDATETIME
, LOCALTIME
, OFFSETDATETIME
, OFFSETTIME
, ZONEDDATETIME
.Validierungseigenschaften:
datePattern
: nur für die Zieltypen DATE
, LOCALDATE
, LOCALDATETIME
, LOCALTIME
, OFFSETDATETIME
, OFFSETTIME
und ZONEDDATETIME
. Definiert das zu verwendende Datumsmuster.maxSize, minSize
: maximale/minimale Länge des Werts.maxDigits, minDigits
: nur für numerische Typen. Maximale/minimale Anzahl an Ziffern.regexPattern
: Regex-Muster.decimalFormat
: nur für dezimale numerische Typen. Standard #.##
Andere:
sortable
: Wenn false, kann das Feld für die Suche verwendet werden, kann jedoch nicht zum Sortieren verwendet werden. Standard: wahr.trim
: Trimmen anwenden.tags
: nützlich, wenn das Feld „Domänenmodell“ mehreren Entitätsfeldern entsprechen kann (das Beispiel finden Sie weiter unten).allowedFilters
: ausschließlich erlaubte Filter.notAllowedFilters
: nicht erlaubte Filter.likeFilters
: erlaubte Like-Filter ( enthält , startetMit , endetMit ). Standard: wahr.Um das Beispiel fortzusetzen, unsere Entitätsklassen:
@ 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
Schnittstelle Ihr Spring JPA-Repository muss JPASearchRepository<YourEntityClass>
erweitern.
@ Repository
public interface PersonRepository extends JpaRepository < PersonEntity , Long >, JPASearchRepository < PersonEntity > {
}
In Ihrem Manager, in Ihrem Dienst oder wo auch immer Sie das Repository verwenden möchten:
Modus 1 : Definieren Sie eine Karte <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 );
// ...
}
// ...
Modus 2 : Anstelle einer Karte müssen Sie JPASearchInput
verwenden, das hier der Einfachheit halber im JSON-Format angezeigt wird.
{
"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
}
}
Durch Modus 2 ist es möglich, komplexe Filter mit AND
, OR
und NOT
zu verwalten (siehe später).
InvalidFieldException
.InvalidValueException
.JPASearchException
Filtername | Bibliotheksschlüssel | Unterstützte Modi |
---|---|---|
UND | Und | 1, 2 |
ODER | oder | 2 |
NICHT | nicht | 2 |
Im Modus 1 bilden alle Filter ausschließlich eine AND
Suche.
Um die anderen Operatoren OR
und NOT
zu verwenden, müssen Sie Modus 2 verwenden
Filtername | Bibliotheksschlüssel | SQL | Unterstützte Modi | Wert erforderlich |
---|---|---|---|---|
Gleich | Gl | sql_col = val | 1,2 | Ja |
Enthält | enthält | sql_col LIKE '%val%' | 1,2 | Ja |
In | In | sql_col IN (val1, val2, ..., valN) | 1,2 | Ja |
Beginnt mit | beginntmit | sql_col LIKE 'val%' | 1,2 | Ja |
Endet mit | endetmit | sql_col LIKE '%val' | 1,2 | Ja |
Größer als | gt | sql_col > val | 1,2 | Ja |
Größer als oder gleich | gte | sql_col >= val | 1,2 | Ja |
Weniger als | lt | sql_col < val | 1,2 | Ja |
Kleiner oder gleich | lte | sql_col <= val | 1,2 | Ja |
Zwischen | zwischen | sql_col ZWISCHEN val1 UND val2 | 1,2 | Ja |
Null | null | sql_col IST NULL | 1,2 | NEIN |
Leer | leer | sql_collection_col IST NULL | 1,2 | NEIN |
Modus 1
Optionsbeschreibung | Bibliotheksschlüssel |
---|---|
Groß-/Kleinschreibung ignorieren | #ich |
Negation | #N |
Trimmen | #T |
Die Optionsschlüssel müssen an den Filter angehängt werden; zB ?firstName_eq#i=Biagio oder ?firstName_eq#i#n=Biagio
Modus 2
Optionsbeschreibung | Bibliotheksschlüssel (Java-Attribute) |
---|---|
Groß-/Kleinschreibung ignorieren | ignorierenFall |
Negation | negieren |
Trimmen | trimmen |
Für jeden Filter ist es möglich options
zu definieren
{
// ...
{
"operator" : " eq " ,
"key" : " firstName " ,
"value" : " Biagio " ,
"options" : {
"ignoreCase" : true ,
"trim" : false ,
"negate" : true
}
}
// ...
}
Java-Objekt:
@ Data
public static class JPASearchFilterOptions {
private boolean ignoreCase ;
private boolean trim ;
private boolean negate ;
}
Filtername | Schlüssel | Feste Werte |
---|---|---|
Limit (Seitengröße) | Limit | |
Offset (Seitenzahl) | versetzt | |
Sortieren | Sortieren | ASC, DESC |
Modus 1 : zB ?firstName_sort=DESC&_limit=10&_offset=0
Modus 2 : Wert-Root options
:
{
"filter" : {
// ...
},
"options" : {
"sortKey" : " firstName " ,
"sortDesc" : true ,
"pageSize" : 10 ,
"pageOffset" : 1
}
}
Java-Objekt:
@ Data
public static class JPASearchOptions {
private String sortKey ;
private Boolean sortDesc = false ;
private Integer pageSize ;
private Integer pageOffset ;
private List < String > selections ;
}
,
: z. B. ?myField_in=test1,test2 --> Zu suchende Werte: [" test1 ", " test2 "]/,
: z. B. ?myField_in=test1,test2/,test3 --> Werte, nach denen gesucht werden soll: [" test1 ", " test2, test3 "] @Projectable
-Annotation Wenden Sie zunächst die @Projectable
-Annotation auf die Felder in Ihrem Domänenmodell oder alternativ Ihrer JPA-Entität an, die Sie zur Auswahl verfügbar machen möchten . Wenn Sie Felder haben, die Sie in anderen Objekten auswählbar machen möchten, kommentieren Sie diese mit @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 ;
}
}
Mit der Anmerkung können Sie Folgendes angeben:
Kerneigenschaften:
entityFieldKey
: der Name des im Entity-Bean definierten Felds (muss nicht angegeben werden, wenn die Annotation im Entity-Bean verwendet wird). Wenn nicht angegeben, ist der Schlüssel der Feldname.JPASearchRepository
Schnittstelle Ihr Spring JPA-Repository muss JPAProjectionRepository<YourEntityClass>
erweitern.
@ Repository
public interface PersonRepository extends JpaRepository < PersonEntity , Long >, JPASearchRepository < PersonEntity >, JPAProjectionRepository < PersonEntity > {
}
In Ihrem Manager, in Ihrem Dienst oder wo auch immer Sie das Repository verwenden möchten:
Modus 1 : Definieren Sie eine Karte (oder fügen Sie sie zur Karte hinzu, die für die Suche nach Modus 1 verwendet wird):
,
// ...
@ 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
}
// ...
Modus 2 : Anstelle einer Karte müssen Sie JPASearchInput
verwenden, das hier der Einfachheit halber im JSON-Format angezeigt wird.
{
"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 "
]
}
}
Für beide Modi gibt die Projektion ein List<Map<String, Object>>-Ergebnis zurück, wobei die Kartenstruktur und die Schlüssel die Entitätsstruktur widerspiegeln (zur Verdeutlichung toJson(entityList) == toJson(mapList) ).
Hinweis 1:
Seien Sie vorsichtig: Die Standardprojektion erzwingt, dass alle Join-Beziehungen LEFT JOIN sind. Wenn Sie dieses Verhalten nicht wünschen, verwenden Sie die Repository-Methoden (Methoden mit dem Suffix „Classic“), mit denen Sie möglicherweise nur die Beziehungen ändern können, die Sie ändern möchten
Hinweis 2:
Unabhängig davon, ob Sie es möchten oder nicht, extrahiert die Projektion immer die Felder, die die Primärschlüssel einer Entität (oder verwandter Entitäten) darstellen.
Hinweis 3:
Paginierung wird nicht unterstützt
InvalidFieldException
.JPASearchException
Es ist möglich, Verknüpfungen mit Fetch zu erzwingen, damit Hibernate (oder Ihr JPA-Framework) eine einzelne Abfrage für die in der Entität definierten Beziehungen ausführen kann. Dies ist nur ohne Paginierung möglich :
// ...
Map < String , JoinFetch > fetches = Map . of ( "companyEntity" , JoinFetch . LEFT );
personRepository . findAll ( filters , Person . class , fetches );
// ...
Wenn Sie über ein Domänenmodell verfügen, das das Ergebnis der Konvertierung mehrerer Entitäten ist, können Sie explizit eine Zuordnung (Zeichenfolge, Zeichenfolge) angeben, deren Schlüssel den Namen des Domänenmodellfelds darstellt und deren Wert der Name des Felds von ist die Entität, nach der gesucht werden soll:
// ...
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 );
// ...
Ein weiterer Sonderfall könnte sein, dass ein Objekt innerhalb des Domänenmodells wiederholt werden kann, um mehrere Teile der Entität darzustellen. Die Lösung für die Suche:
@ 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 '
Bitte beachten Sie: Diese Bibliothek stellt keine Endpunkte und daher keine Controller bereit. Ein ausführliches und vollständiges Beispielprojekt finden Sie hier.
Regler:
@ 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-/Manager-Bean:
@ 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 ) {
// ...
}
}
Locken:
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 '
oder
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 '
Regler:
@ 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-/Manager-Bean:
@ 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 ) {
// ...
}
}
Locken:
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 '
oder
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 '