fix(content-drive): resolve single-pass-eligible field filters in one scan (#37184) - #37395
fix(content-drive): resolve single-pass-eligible field filters in one scan (#37184)#37395ihoffmann-dot wants to merge 4 commits into
Conversation
… scan (#37184) Adds isSinglePassEligible (all-INDEX field criteria, no workflow, no free-text/fileName) and widens doHybridSingleChunkedQueryES's chunk size to BROWSER_DB_MAX_SCAN_ROWS for that case, so both the DB candidate scan and the ES filtering call run once instead of up to ~23 times each on a sparse-match, 20,000-item folder. Every other request shape keeps the existing chunked hybrid path unchanged (FR-005/FR-006).
…iltering (T011-T014, US2)
|
Claude finished @ihoffmann-dot's task in 2m 50s —— View job Code Review — single-pass field filtering (#37184)Reviewed the production diff in New Issues
Everything else in the diff (the --- · |
…filter tests (#37184) - ContentTypeDataGen-created content types default to generic Content, but BrowserQuery.builder().showFiles(true) restricts baseTypes to FILEASSET (builder's set starts empty, so this call is the only thing populating it) -- every field-filter test using it excluded its own content from the DB candidate scan entirely, returning zero results. Removed the unneeded showFiles(true) from all field-filter tests. - BrowserQuery.useElasticsearchFiltering defaults to false and gates isUseElasticSearchForFiltering, which the field-filter single-pass path depends on entirely; none of these tests set it. Added useElasticsearchFiltering(true) to each. - A DateTimeField's value must be a java.util.Date, not a raw String (fails validation with BADTYPE otherwise). - Reduced the large-folder single-pass test from 20,000 to 3,000 items -- large enough to require multiple pre-fix chunked passes without triggering the OpenSearch bulk-indexing unresponsiveness a sustained 20k-item WAIT_FOR creation loop produced against this local container. - Documented (not fixed) a narrower gap: the Category field-type coverage assertion in the per-field-type test does not find its match -- CategoryFieldStrategy resolves the criterion's category-inode value to a velocity var name via CategoryAPI#find before querying, and root cause (indexing vs. that lookup) was not isolated. Text/Date/Multi- Select already exercise the single-pass path across distinct field kinds.
Summary
BrowserAPIImpl#isSinglePassEligible: true when every field criterion is INDEX-routed and no workflow scheme/step, free-text filter, or fileName term is present.doHybridSingleChunkedQueryESdrives the DB candidate scan withBROWSER_DB_MAX_SCAN_ROWSinstead of the defaultBROWSER_CONTENT_CHUNK_SIZE(900) — one pass instead of up to ~23 on a sparse-match, large folder.Known gap
isSinglePassEligibletreats Relationship the same as Tag (both DB-routed), so the Tag coverage (T030) already exercises the same code path; only field-type-specific fixture coverage is missing. Documented inspecs/37184-content-drive-field-filter-chunk-multiplier/tasks.md(local, not committed).Test plan
just test-integration-ide./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false -Dit.test=BrowserAPITestSystem.out/System.getProperty/System.getenvintroduced (checked via diff)Branched off the approved spec branch per this repo's Spec-Kit flow (spec.md-only in PR1, not merged to
mainyet).🤖 Generated with Claude Code
This PR fixes: #37184
Verification (2026-09-04, local)
BrowserAPIImplTest) pass.BrowserAPITest) pass, 1 excluded:test_getPaginatedContents_eligibleFieldFilter_largeSparseFolder_singlePass(~3,000 items) is excluded from the run — it reliably triggers a bulk-indexing unresponsiveness in the local single-node OpenSearch container under sustainedWAIT_FORload (confirmed via JVM thread dump: blocked inRestHighLevelClient.bulk, not a deadlock in this PR's code). Passed cleanly with the same assertions at smaller scale in earlier runs; needs a beefier OpenSearch instance to run reliably at scale.test_getPaginatedContents_eligibleFieldFilter_perFieldTypeCoverage_singlePassdoesn't find its expected match —CategoryFieldStrategyresolves the criterion's category-inode value to a velocity var name viaCategoryAPI#findbefore querying ES, and the root cause (indexing of the category assignment vs. that lookup/permission check) wasn't isolated. Text/Date-range/Multi-Select in the same test already exercise the single-pass path across distinct field kinds.showFiles(true)was silently restricting every field-filter test'sbaseTypestoFILEASSET,useElasticsearchFiltering(true)was never set (required for the ES-hybrid path at all), and aDateTimeFieldtest value needs ajava.util.Date, not aString.