fix(viewtools): normalize query in raw() search path (#36026)#36170
Conversation
|
Claude finished @fabrizzio-dotCMS's task in 1m 38s —— View job Rollback Safety Analysis
Result: ✅ Safe To RollbackAfter analyzing the diff against all categories in the rollback-unsafe reference, this PR does not match any unsafe category. AnalysisThe PR makes the following changes:
Category-by-category reasoning:
Label applied: |
The raw() / esRaw() Velocity search path forwarded the query verbatim while search() / esSearch() lowercased the whole query via StringUtils.lowercaseStringExceptMatchingTokens. A camelCase aggregation field such as "contentType" therefore resolved under search() (folded to the physical lowercase index field "contenttype") but aggregated over a non-existent field under raw(), returning empty buckets silently — the regression reported against the aggregation-tree change. Fix: apply the same lowercasing the search path already uses at the entry of both raw paths (enterprise ESSearchAPIImpl.esSearchRaw and OSSearchAPIImpl.searchRaw), so raw() reaches full parity with search() for mixed-case field names. The call is idempotent for the search() path, which delegates here after already lowercasing. This is the minimal change: one reused helper invocation per raw path, no new API. Tests: ContentSearchToolTest asserts raw(camelCase) reaches parity with search() (same bucket count), and RAW_VTL now drives the customer's camelCase field end-to-end through Velocity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
49bcae4 to
d9bb3ef
Compare
❌ Codex Review failed —
|
wezell
left a comment
There was a problem hiding this comment.
Good. The lowercasing is hard. Glad you found the fix.
Proposed Changes
Follow-up fix for #36026 (the merged change was marked QA : Failed).
Problem
The Velocity
$estool.raw(...)/$estool.esRaw(...)search path forwards the query verbatim, while$estool.search(...)/esSearch(...)lowercases the whole query viaStringUtils.lowercaseStringExceptMatchingTokensbefore executing it. As a result, a camelCase aggregation field such as"field":"contentType":search()— folded to the physical lowercase index fieldcontenttype, andraw()— it aggregated over a field name that does not exist in the index.This surfaced as "raw() returns empty
getBuckets=[]for aggregations". The aggregation mapping itself was never at fault — both paths map the response through the sameContentSearchResponse.from(...).Root cause (single point)
search/esSearchlowercase the query before delegating to the raw method; the raw method (esSearchRaw/OSSearchAPIImpl.searchRaw) never did.Fix (minimal)
Apply the same lowercasing the search path already uses, at the entry of both raw paths:
enterprise/.../ESSearchAPIImpl.esSearchRaw(String)(ES — covers neutralraw()and deprecatedesRaw())opensearch/OSSearchAPIImpl.searchRaw(String)(OS — symmetric)raw()now reaches full parity withsearch()for mixed-case field names. One reused helper invocation per path, no new API. The call is idempotent for thesearch()path, which delegates here after already lowercasing.Files
ESSearchAPIImpl.java(enterprise) — lowercase the query inesSearchRawOSSearchAPIImpl.java— lowercase the query insearchRawSearchAPI.java,ESContentTool.java— javadoc updated to the consistent contractHow to test
```bash
./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=ContentSearchToolTest
```
rawNormalizesQuery_reachingParityWithSearch—raw(camelCase)now populates buckets and matchessearch(camelCase)andraw(lowercase)bucket counts.rawVtl_rendersTreeAndFlatAggregations— drives the customer's camelCasecontentTypefield end-to-end through Velocity.Checklist
BUILD SUCCESS)ContentSearchToolTest)Fixes #36026
🤖 Generated with Claude Code
This PR fixes: #36026