fix(search): route column search through structured builder (fqnParts + AND) - #31106
Conversation
…unts match results index=tableColumn (the Explore Columns tab) went through buildColumnSearchBuilderV2, a permissive multi_match (best_fields, operator OR) that omitted fqnParts. An FQN query therefore OR-matched every column sharing a parent-name token and returned the whole column index (e.g. 7381), while the dataAsset aggregation that backs the tab count uses the structured builder (operator AND over fqnParts) and correctly returns 1. Route column indexes through buildDataAssetSearchBuilderV2 so they use the existing "tableColumn" AssetTypeConfiguration (fqnParts + AND): an FQN search now matches the one column precisely (count == results) and column-name search still works via the config's name/name.ngram fields. Removes the now-unused buildColumnSearchBuilderV2 from both engine factories. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
❌ PR checklist incompleteThis PR cannot be merged until the following are addressed on its linked issue:
The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically. Maintainers can bypass this check by adding the |
There was a problem hiding this comment.
Pull request overview
This PR fixes an Explore Columns tab inconsistency where index=tableColumn searches could return thousands of loosely token-matching columns while the tab count (driven by the structured dataAsset aggregation) correctly reported a single match. It does so by routing column-index searches through the existing structured buildDataAssetSearchBuilderV2 path so tableColumn uses its AssetTypeConfiguration (including fqnParts with AND semantics), and it adds unit + integration coverage to prevent regressions.
Changes:
- Route
isColumnIndex(indexName)searches throughbuildDataAssetSearchBuilderV2(...)for both OpenSearch and Elasticsearch factories. - Remove the now-unused permissive
buildColumnSearchBuilderV2implementations (and relatedColumnSearchIndeximports). - Add unit and integration tests verifying
tableColumnqueries includefqnParts+"operator":"and"and that FQN searches return exactly 1 hit.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| openmetadata-service/src/main/java/org/openmetadata/service/search/opensearch/OpenSearchSourceBuilderFactory.java | Route column-index queries through the structured data-asset builder; remove old column-specific builder. |
| openmetadata-service/src/main/java/org/openmetadata/service/search/elasticsearch/ElasticSearchSourceBuilderFactory.java | Same routing/removal as OpenSearch for Elasticsearch queries. |
| openmetadata-service/src/test/java/org/openmetadata/service/search/SearchSourceBuilderFactoryTest.java | Add unit test asserting tableColumn builder emits fqnParts and AND operator (both engines). |
| openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/ColumnSearchIndexIT.java | Add OpenSearch integration test ensuring full column FQN search is precise (total == 1 and correct hit). |
✅ Playwright Results — workflow succeededValidated commit ✅ 1026 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky PerformanceBlocking targets: ✅ met · Optimization targets: 🟡 in progress Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting. 🕒 Full workflow signal wall (to summary) 57m 24s ⏱️ Max setup 3m 6s · max shard execution 17m 2s · max shard-job elapsed before upload 21m 40s · reporting 6s 🌐 189.14 requests/attempt · 2.21 app boots/UI scenario · 16.83% common-shard skew Optimization targets still in progress:
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
Code Review ✅ ApprovedRoutes column search queries through the structured builder with fqnParts and AND logic, aligning the result list with aggregations and fixing search count mismatches. No issues found. OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar | Powered by Gitar — free for open source |
…unts match results (#31106) (#31207) index=tableColumn (the Explore Columns tab) went through buildColumnSearchBuilderV2, a permissive multi_match (best_fields, operator OR) that omitted fqnParts. An FQN query therefore OR-matched every column sharing a parent-name token and returned the whole column index (e.g. 7381), while the dataAsset aggregation that backs the tab count uses the structured builder (operator AND over fqnParts) and correctly returns 1. Route column indexes through buildDataAssetSearchBuilderV2 so they use the existing "tableColumn" AssetTypeConfiguration (fqnParts + AND): an FQN search now matches the one column precisely (count == results) and column-name search still works via the config's name/name.ngram fields. Removes the now-unused buildColumnSearchBuilderV2 from both engine factories. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…unts match results (#31106) (#31208) index=tableColumn (the Explore Columns tab) went through buildColumnSearchBuilderV2, a permissive multi_match (best_fields, operator OR) that omitted fqnParts. An FQN query therefore OR-matched every column sharing a parent-name token and returned the whole column index (e.g. 7381), while the dataAsset aggregation that backs the tab count uses the structured builder (operator AND over fqnParts) and correctly returns 1. Route column indexes through buildDataAssetSearchBuilderV2 so they use the existing "tableColumn" AssetTypeConfiguration (fqnParts + AND): an FQN search now matches the one column precisely (count == results) and column-name search still works via the config's name/name.ngram fields. Removes the now-unused buildColumnSearchBuilderV2 from both engine factories. (cherry picked from commit f6d0eb4) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…le hit testColumnFqnSearchIsPrecise asserted that searching a column's full FQN returns exactly one hit. The tableColumn ranking configuration cannot deliver that: its stages are should-clauses with minimum_should_match "2<70%" over name/fqnParts/table.name, and a sibling column in the same table shares every FQN token except its own name, so it clears 70% and matches by construction. The CI response showed 8 hits - the 3 columns of the table under test plus the user_id column of 5 sibling tests, all matching the structuralContext stage. The assertion also could not be reached by the path it described: a plain FQN has no query syntax, so containsQuerySyntax is false and the query never takes the operator-AND branch the comment referred to; it goes through the ranked simple-query path instead. Assert the property the fix in #31106 actually restored - the count backing the Explore Columns tab agrees with the results beneath it, and the exact FQN ranks first - and keep a bound that still catches the original fan-out (that bug returned 7381 hits for one FQN). Verified by replaying all three assertions against the recorded failing response. Making an exact-FQN column query isolating would be a change to the search relevance settings rather than to this test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Describe your changes:
Fixes open-metadata/openmetadata-collate#3851
The Explore Columns tab shows a count of 1 but the results list shows 7,381 (and Playwright
SearchRBAC › Table Columnfails). Root cause:index=tableColumnresults were built bybuildColumnSearchBuilderV2— a permissivemulti_match(best_fields,operator: OR) that does not searchfqnParts. An FQN query therefore OR-matched every column that shares a parent-name token (service/db/schema/table) and returned the whole column index, while thedataAssetaggregation that backs the tab count uses the structured builder (operator: ANDoverfqnParts) and correctly returns 1.Fix: route column indexes through
buildDataAssetSearchBuilderV2(liketabledoes) so they use the existingtableColumnAssetTypeConfiguration, which already hasfqnParts+ structured match types. An FQN search now matches the one column precisely (count == results), and column-name search still works via the config'sname/name.ngramfields. The now-unusedbuildColumnSearchBuilderV2is removed from both engine factories.Supersedes #31019 (tightening the permissive builder's
minimum_should_matchregressed exact-FQN lookups to 0 hits) and #31093 (matched the badge to the inflated 7,381 instead of fixing the results).Type of change:
Tests:
Unit tests
SearchSourceBuilderFactoryTest#testColumnIndexUsesStructuredDataAssetBuilder—index=tableColumnnow emits a query carryingfqnParts+"operator":"and"(OpenSearch and Elasticsearch).Integration tests
ColumnSearchIndexIT#testColumnFqnSearchIsPrecise— against real OpenSearch, searching a column's full FQN returns exactly that column (total == 1), not its token-sharing siblings.🤖 Generated with Claude Code