REST Query Language - Implementering ELLER drift

REST Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN Denne artikel er en del af en serie: • REST Query Language with Spring and JPA Criteria

• REST-forespørgselssprog med forårsdata JPA-specifikationer

• REST forespørgselssprog med Spring Data JPA og Querydsl

• REST-forespørgselssprog - Avanceret søgning

• REST Query Language - Implementering ELLER Operation (nuværende artikel) • REST Query Language med RSQL

• REST forespørgselssprog med Querydsl Web Support

1. Oversigt

I denne hurtige artikel udvider vi de avancerede søgefunktioner, som vi implementerede i den foregående artikel og inkluderer ELLER-baserede søgekriterier i vores REST API-forespørgselssprog.

2. Implementeringsmetode

Før alle kriterierne i Søg forespørgselsparameter dannede prædikater, der kun er grupperet efter AND-operator. Lad os ændre det.

Vi skal være i stand til at implementere denne funktion enten som en simpel, hurtig ændring af eksisterende tilgang eller en ny fra bunden.

Med den enkle tilgang markerer vi kriterierne for at indikere, at det skal kombineres ved hjælp af OR-operatøren.

Her er f.eks. URL'en til at teste API'et for "fornavn ELLER efternavn ”:

// localhost: 8080 / brugere? search = firstName: john, 'lastName: doe

Bemærk, at vi har markeret kriterierne efternavn med et enkelt tilbud for at differentiere det. Vi indfanger dette prædikat for OR-operatøren i vores kriterieværdiobjekt - SpecSearchCriteria:

public SpecSearchCriteria (String orPredicate, String key, SearchOperation operation, Object value) {super (); this.orPredicate = orPredicate! = null && orPredicate.equals (SearchOperation.OR_PREDICATE_FLAG); this.key = nøgle; this.operation = operation; this.value = værdi; }

3. UserSpecificationBuilder Forbedring

Lad os nu ændre vores specifikationsbygger, UserSpecificationBuilder, at overveje ELLER kvalificerede kriterier ved konstruktion Specifikation:

public Specification build () {if (params.size () == 0) {return null; } Specifikationsresultat = ny brugerspecifikation (params.get (0)); for (int i = 1; i <params.size (); i ++) {result = params.get (i) .isOrPredicate ()? Specification.where (result) .or (new UserSpecification (params.get (i))): Specification.where (result) .and (new UserSpecification (params.get (i))); } returnere resultat }

4. UserController Forbedring

Lad os endelig oprette et nyt REST-slutpunkt i vores controller til at bruge denne søgefunktionalitet med OR-operatøren. Den forbedrede parselogik udtrækker det specielle flag, der hjælper med at identificere kriterierne med OR-operatøren:

@GetMapping ("/ brugere / espec") @ResponseBody offentlig Liste findAllByOrPredicate (@RequestParam String-søgning) {Specification spec = resolSpecification (search); returner dao.findAll (spec); } beskyttet Specification resolSpecification (String searchParameters) {UserSpecificationsBuilder builder = new UserSpecificationsBuilder (); String operationSetExper = Joiner.on ("|") .join (SearchOperation.SIMPLE_OPERATION_SET); Mønster mønster = Mønster.kompil ("(\ p {Punct}?) (\ w +?) (" + OperationSetExper + ") (\ p {Punct}?) (\ w +?) (\ p { Punct}?), "); Matcher matcher = pattern.matcher (searchParameters + ","); mens (matcher.find ()) {builder.with (matcher.group (1), matcher.group (2), matcher.group (3), matcher.group (5), matcher.group (4), matcher. gruppe (6)); } returner builder.build (); }

5. Live test med ELLER Tilstand

I dette live-testeksempel med det nye API-slutpunkt søger vi efter brugere med fornavnet "john" ELLER efternavn "doe". Bemærk denne parameter efternavn har et enkelt tilbud, der kvalificerer det som et "ELLER predikat":

privat String EURL_PREFIX = "// localhost: 8082 / spring-rest-full / auth / users / espec? search ="; @Test public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect () {Response response = givenAuth (). Get (EURL_PREFIX + "firstName: john, 'lastName: doe"); String result = response.body (). AsString (); assertTrue (result.contains (userJohn.getEmail ())); assertTrue (result.contains (userTom.getEmail ())); }

6. Udholdenhedstest med ELLER Tilstand

Lad os nu udføre den samme test, som vi gjorde ovenfor, på persistensniveauet for brugerne med fornavn “john” ELLER efternavn “doe”:

@ Test offentlig ugyldighed givenFirstOrLastName_whenGettingListOfUsers_thenCorrect () {UserSpecificationsBuilder builder = new UserSpecificationsBuilder (); SpecSearchCriteria spec = ny SpecSearchCriteria ("fornavn", SearchOperation.EQUALITY, "john"); SpecSearchCriteria spec1 = ny SpecSearchCriteria ("'", "efternavn", SearchOperation.EQUALITY, "doe"); Listeresultater = repository .findAll (builder.with (spec) .with (spec1) .build ()); assertThat (resultater, hasSize (2)); assertThat (userJohn, isIn (resultater)); assertThat (userTom, isIn (resultater)); }

7. Alternativ tilgang

I den alternative tilgang kunne vi give søgeforespørgslen mere som en komplet HVOR klausul om SQL-forespørgsel.

For eksempel er her URL'en til en mere kompleks søgning efter fornavn og alder:

// localhost: 8080 / brugere? search = (fornavn: john ELLER fornavn: tom) OG alder> 22

Bemærk, at vi har adskilt individuelle kriterier, operatorer & gruppeparenteser med et mellemrum for at danne et gyldigt infix-udtryk.

Lad os analysere infix-udtrykket med a KriterierParser. Vores KriterierParser opdeler det givne infix-udtryk i tokens (kriterier, parentes, AND & OR-operatorer) og opretter et postfix-udtryk for det samme:

public Deque parse (String searchParam) {Deque output = new LinkedList (); Deque stack = ny LinkedList (); Arrays.stream (searchParam.split ("\ s +")). ForEach (token -> {if (ops.containsKey (token)) {while (! Stack.isEmpty () && isHigerPrecedenceOperator (token, stack.peek () )) {output.push (stack.pop (). er lig medIgnoreCase (SearchOperation.OR_OPERATOR)? SearchOperation.OR_OPERATOR: SearchOperation.AND_OPERATOR);} stack.push (token.equalsIgnoreCase (SearchOperation.OR_OPERATOR)? SearchOperation.OR_OPERATION.OR_Operation.OR_ );} ellers hvis (token.equals (SearchOperation.LEFT_PARANTHESIS)) {stack.push (SearchOperation.LEFT_PARANTHESIS);} ellers hvis (token.equals (SearchOperation.RIGHT_PARANTHESIS)) {mens (! stack.peek (). er lig med ( SearchOperation.LEFT_PARANTHESIS)) {output.push (stack.pop ());} stack.pop ();} ellers {Matcher matcher = SpecCriteraRegex.matcher (token); while (matcher.find ()) {output.push ( ny SpecSearchCriteria (matcher.group (1), matcher.group (2), matcher.group (3), matcher.group (4), matcher.group (5)));}}}); mens (! stack.isEmpty ()) {output.push (stack.pop ()); } returnere output; }

Lad os tilføje en ny metode i vores specifikationsbygger, GenericSpecificationBuilder, at konstruere søgningen Specifikation fra postfix-udtrykket:

 public Specification build (Deque postFixedExprStack, Function konverter) {Deque specStack = ny LinkedList (); while (! postFixedExprStack.isEmpty ()) {Object mayBeOperand = postFixedExprStack.pollLast (); hvis (! (mayBeOperand forekomst af streng)) {specStack.push (converter.apply ((SpecSearchCriteria) mayBeOperand)); } andet {Specification operand1 = specStack.pop (); Specifikation operand2 = specStack.pop (); hvis (mayBeOperand.equals (SearchOperation.AND_OPERATOR)) {specStack.push (Specification.where (operand1) .and (operand2)); } ellers hvis (mayBeOperand.equals (SearchOperation.OR_OPERATOR)) {specStack.push (Specification.where (operand1) .or (operand2)); }}} returner specStack.pop ();

Lad os endelig tilføje et andet REST-slutpunkt i vores UserController at analysere det komplekse udtryk med det nye KriterierParser:

@GetMapping ("/ users / spec / adv") @ResponseBody public List findAllByAdvPredicate (@RequestParam String search) {Specification spec = resolSpecificationFromInfixExpr (search); returner dao.findAll (spec); } beskyttet Specification resolSpecificationFromInfixExpr (String searchParameters) {CriteriaParser parser = new CriteriaParser (); GenericSpecificationsBuilder specBuilder = ny GenericSpecificationsBuilder (); returner specBuilder.build (parser.parse (searchParameters), UserSpecification :: new); }

8. Konklusion

I denne vejledning har vi forbedret vores REST-forespørgselssprog med muligheden for at søge med en OR-operatør.

Den fulde implementering af denne artikel kan findes i GitHub-projektet. Dette er et Maven-baseret projekt, så det skal være let at importere og køre som det er.

Næste » REST Query Language med RSQL « Tidligere REST-forespørgselssprog - Avanceret søgning REST nederst

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

$config[zx-auto] not found$config[zx-overlay] not found