REST Query Language - Implementering ELLER drift

REST Topp

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET Denne artikkelen er en del av en serie: • REST Query Language with Spring and JPA Criteria

• REST-spørrespråk med vårdata JPA-spesifikasjoner

• REST Query Language med vårdata JPA og Querydsl

• REST-spørrespråk - Avanserte søkeoperasjoner

• REST Query Language - Implementering OR Operation (nåværende artikkel) • REST Query Language med RSQL

• REST Query Language med Querydsl Web Support

1. Oversikt

I denne raske artikkelen utvider vi de avanserte søkeoperasjonene som vi implementerte i forrige artikkel og inkluderer ELLER-baserte søkekriterier i vårt REST API Query Language.

2. Implementeringsmetode

Før, alle kriteriene i Søk spørringsparameter dannet predikater bare gruppert av AND-operator. La oss endre det.

Vi skal kunne implementere denne funksjonen enten som en enkel, rask endring av eksisterende tilnærming eller en ny fra bunnen av.

Med den enkle tilnærmingen vil vi flagge kriteriene for å indikere at det må kombineres ved hjelp av OR-operatøren.

Her er for eksempel URL-en for å teste API-en for “fornavn ELLER etternavn ”:

// localhost: 8080 / brukere? search = fornavn: john, 'etternavn: doe

Merk at vi har flagget kriteriene etternavn med et enkelt sitat for å skille det. Vi vil fange dette predikatet for OR-operatøren i vårt kriterieverdiobjekt - 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økkel; this.operation = operasjon; this.value = verdi; }

3. UserSpecificationBuilder Forbedring

La oss endre spesifikasjonsbyggeren vår, UserSpecificationBuilder, å vurdere ELLER kvalifiserte kriterier ved konstruksjon Spesifikasjon:

public Specification build () {if (params.size () == 0) {return null; } Spesifikasjonsresultat = ny brukerspesifikasjon (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

Til slutt, la oss sette opp et nytt REST-endepunkt i kontrolleren vår for å bruke denne søkefunksjonaliteten med OR-operatøren. Den forbedrede parselogikken trekker ut det spesielle flagget som hjelper til med å identifisere kriteriene med OR-operatøren:

@GetMapping ("/ users / espec") @ResponseBody public List findAllByOrPredicate (@RequestParam String search) {Spesifikasjon spesifikasjon = resolutionSpecification (søk); returner dao.findAll (spesifikasjon); } beskyttet Spesifikasjon resolSpecification (String searchParameters) {UserSpecificationsBuilder builder = new UserSpecificationsBuilder (); String operationSetExper = Joiner.on ("|"). Join (SearchOperation.SIMPLE_OPERATION_SET); Mønstermønster = Mønster.kompilere ("(\ p {Punct}?) (\ w +?) (" + OperationSetExper + ") (\ p {Punct}?) (\ w +?) (\ p { Punct}?), "); Matcher matcher = mønster.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-testeksemplet, med det nye API-endepunktet, søker vi etter brukere med fornavnet “john” ELLER etternavnet “doe”. Merk deg parameteren etternavn har et enkelt sitat, som kvalifiserer det som et "ELLER predikat":

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

6. Utholdenhetstest med ELLER Tilstand

La oss nå utføre den samme testen som vi gjorde ovenfor, på utholdenhetsnivået for brukerne med fornavn “john” ELLER etternavn “doe”:

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

7. Alternativ tilnærming

I den alternative tilnærmingen kan vi gi søkeordet mer som en komplett HVOR klausul om SQL-spørring.

Her er for eksempel URL-en for et mer komplekst søk av fornavn og alder:

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

Merk at vi har skilt individuelle kriterier, operatorer og grupperingsparenteser med et mellomrom for å danne et gyldig infiksuttrykk.

La oss analysere infix-uttrykket med a KriterierParser. Våre KriterierParser deler det gitte infix-uttrykket i tokens (kriterier, parentes, AND & OR-operatorer) og lager et postfix-uttrykk for det samme:

public Deque parse (String searchParam) {Deque output = new LinkedList (); Deque stack = new LinkedList (); Arrays.stream (searchParam.split ("\ s +")). ForEach (token -> {if (ops.containsKey (token)) {while (! Stack.isEmpty () && isHigerPrecedenceOperator (token, stack.peek () )) {output.push (stack.pop (). equalsIgnoreCase (SearchOperation.OR_OPERATOR)? SearchOperation.OR_OPERATOR: SearchOperation.AND_OPERATOR);} stack.push (token.equalsIgnoreCase (SearchOperation.OR_OPERATOR)? SearchOperation.OR_OPERATION.OR_OPERATOR.OR_OPERATOR)? );} annet hvis (token.equals (SearchOperation.LEFT_PARANTHESIS)) {stack.push (SearchOperation.LEFT_PARANTHESIS);} annet hvis (token.equals (SearchOperation.RIGHT_PARANTHESIS)) {mens (! stack.peek (). er lik ( SearchOperation.LEFT_PARANTHESIS)) {output.push (stack.pop ());} stack.pop ();} else {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)));}}}); while (! stack.isEmpty ()) {output.push (stack.pop ()); } returnere utdata; }

La oss legge til en ny metode i vår spesifikasjonsbygger, GenericSpecificationBuilder, for å konstruere søket Spesifikasjon fra postfix-uttrykket:

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

Til slutt, la oss legge til et annet REST-sluttpunkt i vårt UserController å analysere det komplekse uttrykket med det nye KriterierParser:

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

8. Konklusjon

I denne veiledningen har vi forbedret REST-spørringsspråket vårt med muligheten til å søke med en OR-operatør.

Den fulle implementeringen av denne artikkelen finner du i GitHub-prosjektet. Dette er et Maven-basert prosjekt, så det skal være enkelt å importere og kjøre som det er.

Neste » REST Query Language med RSQL « Previous REST Query Language - Advanced Search Operations REST bottom

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

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