如何调整JHipster生成的查询逻辑,实现storeName或identifier的OR条件模糊查询?
The Problem
Right now, your code is fetching cash registers where both storeName and identifier contain your search term event.query. You need to adjust this to return results where either field matches the term. Here's your current frontend query code:
this.cashRegisterService .query({ 'storeName.contains': event.query, 'identifier.contains': event.query, }) .subscribe(data => { this.cashregisters = (data.body || []).map(cashRegister => ({ id: cashRegister.id, name: `${cashRegister.identifier} ${cashRegister.storeName} (${cashRegister.mallName})`, })); });
And here's the JHipster-generated service and request option helper code you're using:
// CashRegisterService's query method query(req?: any): Observable<EntityArrayResponseType> { const options = createRequestOption(req); return this.http.get<ICashRegister[]>(this.resourceUrl, { params: options, observe: 'response' }); } // createRequestOption function export const createRequestOption = (req?: any): HttpParams => { let options: HttpParams = new HttpParams(); if (req) { Object.keys(req).forEach(key => { if (key !== 'sort') { options = options.set(key, req[key]); } }); if (req.sort) { req.sort.forEach((val: string) => { options = options.append('sort', val); }); } } return options; };
The Solution
JHipster's backend relies on Spring Data REST, which supports OR logic via the or query parameter. We need to tweak both your frontend query structure and the createRequestOption function to handle this correctly (the original function uses set() which overwrites duplicate keys, but OR requires repeating the or parameter for each condition).
Step 1: Update the Frontend Query
Replace your current query object with an or array containing each of your match conditions. This tells the backend to treat these criteria as OR'd:
this.cashRegisterService .query({ or: [ { 'storeName.contains': event.query }, { 'identifier.contains': event.query } ] }) .subscribe(data => { this.cashregisters = (data.body || []).map(cashRegister => ({ id: cashRegister.id, name: `${cashRegister.identifier} ${cashRegister.storeName} (${cashRegister.mallName})`, })); });
Step 2: Modify the createRequestOption Function
The original helper doesn't process the or array properly. We need to loop through the array, convert each condition to the format Spring Data REST expects (property.queryMethod:value), and append each as a separate or parameter:
export const createRequestOption = (req?: any): HttpParams => { let options: HttpParams = new HttpParams(); if (req) { Object.keys(req).forEach(key => { if (key !== 'sort') { // Handle OR conditions specially if (key === 'or' && Array.isArray(req[key])) { req[key].forEach((condition: any) => { const [conditionKey] = Object.keys(condition); const conditionValue = condition[conditionKey]; // Format as "property.queryMethod:value" and append to params options = options.append('or', `${conditionKey}:${conditionValue}`); }); } else { options = options.set(key, req[key]); } } }); if (req.sort) { req.sort.forEach((val: string) => { options = options.append('sort', val); }); } } return options; };
Why This Works
Spring Data REST interprets multiple or parameters as OR'd conditions. Your final request URL will look like this:?or=storeName.contains:yourSearchTerm&or=identifier.contains:yourSearchTerm
The backend automatically translates this into SQL logic:WHERE storeName LIKE '%yourSearchTerm%' OR identifier LIKE '%yourSearchTerm%'
Alternative (No Global Function Modification)
If you don't want to change the global createRequestOption function, you can construct the HttpParams directly in your component:
const searchParams = new HttpParams() .append('or', `storeName.contains:${event.query}`) .append('or', `identifier.contains:${event.query}`); // Call the HTTP client directly instead of using the service's query method this.http.get<ICashRegister[]>(this.cashRegisterService.resourceUrl, { params: searchParams, observe: 'response' }) .subscribe(data => { this.cashregisters = (data.body || []).map(cashRegister => ({ id: cashRegister.id, name: `${cashRegister.identifier} ${cashRegister.storeName} (${cashRegister.mallName})`, })); });
This approach is less reusable but avoids altering the global request helper.
内容的提问来源于stack exchange,提问作者Mihnea Burluc

