Skip to content

Fix search relevance: exact names losing to near matches - #31502

Open
harshach wants to merge 14 commits into
mainfrom
harshach/exact-match-ranking-boost
Open

Fix search relevance: exact names losing to near matches#31502
harshach wants to merge 14 commits into
mainfrom
harshach/exact-match-ranking-boost

Conversation

@harshach

Copy link
Copy Markdown
Collaborator

An exactly-named asset could rank below assets that merely start with the query. Two causes: the text ranking stages were a multi_match boosted by their weight, so a stage scored BM25 x weight and was unbounded, while exactName is a constant_score capped at 100 -- under dis_max a stage configured at 24 measured over 105 and won. And om_compound_analyzer split "customers7" into [customers7, customers, 7], so with fuzziness the query matched two terms in the sibling and Lucene's blended-freq rewrite summed them.

Auditing the rest of the query surface against a real corpus turned up six more defects, all of which broke matching or ordering before ranking could help:

  • om_analyzer lowercased before word_delimiter ran, so split_on_case_change never saw a case boundary and CustomerAddress indexed as one opaque token.
  • kstem leaves orders, sessions, transactions and regions unstemmed while stemming customers and items, so a singular query missed a quarter of the plural names in a catalog. om_plural_stemmer closes those cases behind it.
  • om_compound_analyzer did not stem, so it disagreed with its base field about the same document.
  • displayName falls back to name and name.compound now analyses like name, so the identity stages restated one piece of evidence up to four times and a tie_breaker turned field count into a relevance signal.
  • om_ngram has a three character minimum and encodes no notion of "starts with", so partially typed names ranked arbitrarily and anything shorter matched nothing. Added a prefixName stage using match_bool_prefix.
  • No entity-type prior existed, and the column index carries two orders of magnitude more documents than the table index.
  • stageFieldWeights normalised against the stage's own maximum, so a field's weight depended on what it shared a stage with, and the cross-entity merge let one entity type's niche field set the ceiling for everyone.

Also incorporates PR #31228, which stops the fuzzy stage widening recall on identifier lookups.

The mapping edits change the content hash, so IndexMappingVersionTracker triggers a reindex on upgrade; that is required for the analyzer fixes to take effect.

Describe your changes:

Fixes #

I worked on ... because ...

Type of change:

  • Bug fix
  • Improvement
  • New feature
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation

High-level design:

N/A — small change.

Tests:

Use cases covered

Unit tests

Backend integration tests

Ingestion integration tests

Playwright (UI) tests

Manual testing performed

UI screen recording / screenshots:

Not applicable.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • My PR is linked to a GitHub issue via Fixes #<issue-number> above.
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.
  • For UI changes: I attached a screen recording and/or screenshots above.
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.

An exactly-named asset could rank below assets that merely start with the
query. Two causes: the text ranking stages were a multi_match boosted by
their weight, so a stage scored BM25 x weight and was unbounded, while
exactName is a constant_score capped at 100 -- under dis_max a stage
configured at 24 measured over 105 and won. And om_compound_analyzer split
"customers7" into [customers7, customers, 7], so with fuzziness the query
matched two terms in the sibling and Lucene's blended-freq rewrite summed
them.

Auditing the rest of the query surface against a real corpus turned up six
more defects, all of which broke matching or ordering before ranking could
help:

- om_analyzer lowercased before word_delimiter ran, so split_on_case_change
  never saw a case boundary and CustomerAddress indexed as one opaque token.
- kstem leaves orders, sessions, transactions and regions unstemmed while
  stemming customers and items, so a singular query missed a quarter of the
  plural names in a catalog. om_plural_stemmer closes those cases behind it.
- om_compound_analyzer did not stem, so it disagreed with its base field
  about the same document.
- displayName falls back to name and name.compound now analyses like name,
  so the identity stages restated one piece of evidence up to four times and
  a tie_breaker turned field count into a relevance signal.
- om_ngram has a three character minimum and encodes no notion of "starts
  with", so partially typed names ranked arbitrarily and anything shorter
  matched nothing. Added a prefixName stage using match_bool_prefix.
- No entity-type prior existed, and the column index carries two orders of
  magnitude more documents than the table index.
- stageFieldWeights normalised against the stage's own maximum, so a field's
  weight depended on what it shared a stage with, and the cross-entity merge
  let one entity type's niche field set the ceiling for everyone.

Also incorporates PR #31228, which stops the fuzzy stage widening recall on
identifier lookups.

The mapping edits change the content hash, so IndexMappingVersionTracker
triggers a reindex on upgrade; that is required for the analyzer fixes to
take effect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 14, 2026 02:06
@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Too many files changed for review (226 files, 100 file limit).

Bypass the limit by tagging @greptile-apps to review.

@github-actions

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

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 skip-pr-checks label.

@github-actions github-actions Bot added backend safe to test Add this label to run secure Github workflows on PRs labels Aug 14, 2026
@harshach harshach added the skip-pr-checks Bypass PR metadata validation check label Aug 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ TypeScript Types Auto-Updated

The generated TypeScript types have been automatically updated based on JSON schema changes in this PR.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts OpenMetadata’s search configuration and index analyzers to improve relevance and matching (notably ensuring exact identity matches and better tokenization/stemming behavior), and introduces a new ranking-stage matchType to support prefix-style matching.

Changes:

  • Extend search ranking stage configuration to support a new matchType: "prefix".
  • Update Elasticsearch/OpenSearch index analyzers across many entity mappings (word delimiter ordering, compound analyzer stemming, plural stemming).
  • Add missing UI i18n strings for search ranking/debug explanations and related labels.

Reviewed changes

Copilot reviewed 220 out of 223 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json Adds missing English locale keys used by search ranking/debug UI.
openmetadata-spec/src/main/resources/json/schema/configuration/searchSettings.json Adds "prefix" to the allowed matchType enum for ranking stages.
openmetadata-spec/src/main/resources/elasticsearch/zh/worksheet_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/user_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/topic_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/test_suite_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/test_case_result_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/test_case_resolution_status_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/test_case_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/team_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/zh/tag_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/table_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/stored_procedure_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/storage_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/spreadsheet_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/search_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/search_entity_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/query_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/query_cost_record_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/prompt_template_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/pipeline_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/pipeline_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/mlmodel_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/mlmodel_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/metric_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/metadata_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/messaging_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/mcp_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/mcp_server_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/mcp_execution_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/llm_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/llm_model_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/ingestion_pipeline_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/glossary_term_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/glossary_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/folder_search_index.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/file_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/drive_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/domain_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/directory_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/database_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/database_schema_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/database_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/data_products_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/dashboard_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/dashboard_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/dashboard_data_model_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/context_memory_search_index.json Analyzer updates (word delimiter ordering + plural stemmer).
openmetadata-spec/src/main/resources/elasticsearch/zh/container_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/column_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/classification_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/chart_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/audit_report_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/api_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/api_endpoint_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/api_collection_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/ai_governance_policy_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/ai_governance_framework_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/ai_framework_control_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/zh/ai_application_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/ru/security_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/ru/context_memory_search_index.json Analyzer updates (word delimiter ordering + plural stemmer).
openmetadata-spec/src/main/resources/elasticsearch/jp/worksheet_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/user_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/topic_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/test_suite_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/test_case_result_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/test_case_resolution_status_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/test_case_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/team_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/tag_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/table_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/stored_procedure_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/storage_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/spreadsheet_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/search_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/search_entity_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/query_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/query_cost_record_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/prompt_template_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/pipeline_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/pipeline_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/mlmodel_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/mlmodel_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/metric_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/metadata_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/messaging_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/mcp_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/mcp_server_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/mcp_execution_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/llm_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/llm_model_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/ingestion_pipeline_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/glossary_term_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/glossary_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/folder_search_index.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/file_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/drive_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/domain_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/directory_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/database_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/database_schema_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/database_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/data_products_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/dashboard_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/dashboard_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/dashboard_data_model_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/context_memory_search_index.json Analyzer updates (word delimiter ordering + plural stemmer).
openmetadata-spec/src/main/resources/elasticsearch/jp/container_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/column_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/classification_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/chart_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/audit_report_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/api_service_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/api_endpoint_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/api_collection_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/jp/ai_governance_policy_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/ai_governance_framework_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/ai_framework_control_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/jp/ai_application_index_mapping.json Analyzer updates (plural stemmer + compound analyzer stemming/order).
openmetadata-spec/src/main/resources/elasticsearch/en/worksheet_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/user_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/topic_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/test_suite_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/test_case_result_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/test_case_resolution_status_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/test_case_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/team_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/tag_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/table_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/stored_procedure_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/storage_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/spreadsheet_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/security_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/search_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/search_entity_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/query_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/query_cost_record_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/prompt_template_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/pipeline_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/pipeline_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/mlmodel_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/mlmodel_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/metric_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/metadata_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/messaging_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/mcp_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/mcp_server_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/mcp_execution_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer).
openmetadata-spec/src/main/resources/elasticsearch/en/llm_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/llm_model_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/ingestion_pipeline_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/glossary_term_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/glossary_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/folder_search_index.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/file_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/drive_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/domain_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/directory_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/database_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/database_schema_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/database_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/data_products_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/dashboard_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/dashboard_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/dashboard_data_model_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/context_memory_search_index.json Analyzer updates (word delimiter ordering + plural stemmer).
openmetadata-spec/src/main/resources/elasticsearch/en/container_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/column_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/classification_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/chart_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/audit_report_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/api_service_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/api_endpoint_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/api_collection_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/ai_governance_policy_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/ai_governance_framework_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/ai_framework_control_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-spec/src/main/resources/elasticsearch/en/ai_application_index_mapping.json Analyzer updates (word delimiter ordering + plural stemmer + compound analyzer changes).
openmetadata-service/src/main/java/org/openmetadata/service/search/SearchUtils.java Refactors fuzziness return values to use named constants.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 339 to 343
"matchType": {
"type": "string",
"enum": ["exact", "phrase", "tokenCoverage", "standard", "fuzzy"],
"enum": ["exact", "phrase", "prefix", "tokenCoverage", "standard", "fuzzy"],
"description": "Query strategy for this ranking stage.",
"default": "standard"
Copilot AI review requested due to automatic review settings August 14, 2026 02:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 220 out of 223 changed files in this pull request and generated no new comments.

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 66%
66.81% (79810/119450) 51.21% (48699/95088) 52.19% (14581/27935)

isExactIdentifierLookup now takes a Stream instead of a materialised List.
hasPrunableFuzzyStage is true for the shipped ranking, so the identifier
check ran on every search response and not only on identifier lookups; it
deserialized every hit's source via toJson().asJsonObject() into a
List<JsonObject> and then a second List<String>, work the response
serialization repeats. Consuming lazily bounds it to the hits scanned before
the first match.

Kept detection on document identity rather than gating on query shape. The
comparison is against the literal trimmed query over name/fullyQualifiedName,
so skipping queries that contain whitespace would silently drop the precision
pass for a name that legitimately contains a space.

Dropped the memo in withoutFuzzyStages. It keyed on reference identity and
could never hit: SettingsCache.getSetting runs JsonUtils.convertValue on
every retrieval and the search managers retrieve once per request, so the
cache only held a strong reference to a dead object. Its test asserted the
memo rather than the invariant that matters, and now pins that pruning
returns an independent copy without mutating the settings the widened first
pass still uses.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 14, 2026 02:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 220 out of 223 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 221 out of 224 changed files in this pull request and generated no new comments.

The identity check ran against the window the caller asked for, so the
decision changed with the page. The exactly-named document sits in the top
band: a from=0 request sees it and returns the pruned result set, while a
from=15 request looks at hits 16-30, does not see it, and returns the widened
one. The two pages then disagree about hits.total and about which document is
16th, rows repeat across the boundary, and pruned-set rows past the first page
become unreachable.

SearchPass now takes the window to fetch, and the identity check always judges
the same top-of-ranking slice: the already-fetched page when the caller asked
for from=0 with a large enough size, and a from=0 probe otherwise. The reuse
path is capped to the probe size too, or a large first page would judge on
more hits than a later page's probe and the two could still disagree.

Costs nothing extra on the first page, which is the common case, and one small
request for deeper pages.

everyPageOfOneQueryUsesTheSameResultSet reproduces the corpus that triggers it
-- the identifier only ever in the top window -- and pins from=0, 15 and 300 to
the pruned set. It fails without the fix.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 221 out of 224 changed files in this pull request and generated no new comments.

kstem shortens "customer" to "custom", so a typed "custmer" is three edits
from every stemmed form and fuzziness 1 cannot bridge it. Typo tolerance
worked only because om_compound_analyzer had no stemmer: name.compound held
the literal "customer" one edit away. Stemming that field, and then dropping
it from the identity stages as redundant, removed the sole surface a typo
could land on for every word kstem shortens.

Observed on the live index during the failing run, where the query returned
nothing at all and the seeded table was the only document in the corpus
matching *custom*:

  name("customer_analytics__...") -> [..., custom, analyt, ...]
  name("custmer")                 -> [custmer]

The two fields disagreeing is the design, not duplication to tidy away: one
stemmed, one literal. The score inflation that motivated collapsing them is
handled by the identity stages' zero tie breaker, which scores only the best
field, and that stays.

Compound analyzers are un-stemmed again across the mappings and .compound is
back in the identity stage field lists. The camelCase filter order and the
plural stemmer on the base field are unchanged. Both tests that encoded the
wrong assumption now assert the corrected design and carry the reasoning.

Verified on postgres-opensearch (72 tests) and mysql-elasticsearch (83
tests); testSingleWordTypoStillMatchesViaFuzzy had been timing out on both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 222 out of 225 changed files in this pull request and generated no new comments.

A cursor request carries from=0 while search_after has scrolled it anywhere in
the ranking, so the from==0 shortcut treated its window as the top-of-ranking
identity check. The pruned/widened decision could still flip between pages for
API clients paging with search_after -- the same tear the window pinning was
added to prevent, reached by a second route. The dedicated probe also has to
run without the cursor, or it reads whatever the caller had scrolled to rather
than the actual top.

from and size become a SearchWindow record carrying whether the caller
supplied a cursor. The probe window is never cursor paged, and windowed() in
both managers drops search_after for any non-cursor window.

Also corrects the javadoc, which still claimed an ordinary search costs one
round-trip; pinning the identity window had already made deeper pages pay a
probe plus the page.

aCursorPageIsNotMistakenForTheTopOfTheRanking pins both halves and fails
without the guard, serving the cursor page from the widened set while page one
is pruned.

Reported by tomasmontielp and gitar-bot in review of #31502.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 222 out of 225 changed files in this pull request and generated no new comments.

ScratchDumpQueriesTest was a local harness for dumping generated queries while
auditing relevance. It reads /tmp/om_query_list.txt, which exists only on the
machine that wrote it, so it failed the unit lane with NoSuchFile and took the
whole build down with it. It was never meant to be committed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 221 out of 224 changed files in this pull request and generated no new comments.

tomasmontielp
tomasmontielp previously approved these changes Aug 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 221 out of 224 changed files in this pull request and generated no new comments.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ UI Checkstyle passed — lint findings in changed files

🔍 ESLint findings in this PR's files — 0 error(s), 38 warning(s)

Errors block the build. Warnings do not yet — they are rules whose backlog is still
being worked down, listed so this PR does not add to it. See docs/ui-code-quality-gate.md.

0 error(s), 38 warning(s) across 2 changed file(s).

Count Rule
14 i18next/no-literal-string
12 sonarjs/no-duplicate-string
5 openmetadata-imports/no-circular-imports
3 sonarjs/cyclomatic-complexity
2 react-hooks/exhaustive-deps
1 sonarjs/no-redundant-jump
1 sonarjs/cognitive-complexity
All findings
Location Rule Message
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:94:56 i18next/no-literal-string disallow literal string:
Domain Display
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:208:38 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 8 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:307:26 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 3 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:314:28 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 3 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:513:19 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 7 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:776:47 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 3 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:901:27 i18next/no-literal-string disallow literal string: service-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:907:29 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 6 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:915:15 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 4 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:916:27 i18next/no-literal-string disallow literal string: service-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:921:15 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 4 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:922:27 i18next/no-literal-string disallow literal string: database-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:927:15 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 3 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:928:27 i18next/no-literal-string disallow literal string: databaseSchema-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:934:34 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 4 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:936:29 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 5 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:937:29 sonarjs/no-duplicate-string Define a constant instead of duplicating this literal 3 times.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:946:27 i18next/no-literal-string disallow literal string: service-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:952:27 i18next/no-literal-string disallow literal string: database-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:975:27 i18next/no-literal-string disallow literal string: service-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:981:27 i18next/no-literal-string disallow literal string: database-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:1002:27 i18next/no-literal-string disallow literal string: service-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:1008:27 i18next/no-literal-string disallow literal string: database-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:1014:27 i18next/no-literal-string disallow literal string: databaseSchema-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:1035:27 i18next/no-literal-string disallow literal string: service-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.test.tsx:1041:27 i18next/no-literal-string disallow literal string: databaseSchema-icon
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:42:1 openmetadata-imports/no-circular-imports This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:45:1 openmetadata-imports/no-circular-imports This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:47:1 openmetadata-imports/no-circular-imports This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:50:1 openmetadata-imports/no-circular-imports This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:53:1 openmetadata-imports/no-circular-imports This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:130:3 sonarjs/no-redundant-jump Remove this redundant jump.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:226:5 sonarjs/cognitive-complexity Refactor this function to reduce its Cognitive Complexity from 18 to the 15 allowed.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:226:5 sonarjs/cyclomatic-complexity {"message":"Function has a complexity of 17 which is greater than 10 authorized.","cost":7,"secondaryLocations":[{"line":226,"column":4,"endLine":226,"endColumn
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:368:37 sonarjs/cyclomatic-complexity {"message":"Function has a complexity of 15 which is greater than 10 authorized.","cost":5,"secondaryLocations":[{"line":368,"column":36,"endLine":368,"endColum
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:473:8 react-hooks/exhaustive-deps React Hook useMemo has a missing dependency: 't'. Either include it or remove the dependency array.
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:527:31 sonarjs/cyclomatic-complexity {"message":"Function has a complexity of 11 which is greater than 10 authorized.","cost":1,"secondaryLocations":[{"line":527,"column":30,"endLine":527,"endColum
🟡 src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:634:8 react-hooks/exhaustive-deps React Hook useMemo has missing dependencies: 'classNameForBreadcrumb', 'entityIcon', 'handlePrefetch', 'isTourOpen', 'onCheckboxChange', 'openEntityInNewPage',

Fix locally (fast - only checks files changed in this branch):

make ui-checkstyle-changed

The tag select keeps its dropdown overlay mounted after it closes, and the
matching option carries the same data-testid as the applied tag. An unscoped
page.getByTestId therefore resolves to two elements and the assertion dies on
a strict mode violation rather than on the behaviour under test.

Scope each of the three assertions to the column's tag cell, matching what the
sibling assertions in the same tests already do.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 222 out of 225 changed files in this pull request and generated no new comments.

Suppressed comments (2)

openmetadata-ui/src/main/resources/ui/src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:757

  • This contributor row renders the score prefix using a hardcoded template literal (+${...}). To keep localization consistent, consider moving the entire string (including the leading +) behind a translation key and interpolating the formatted value.
    openmetadata-ui/src/main/resources/ui/src/components/ExploreV1/ExploreSearchCard/ExploreSearchCard.tsx:748
  • This introduces a hardcoded user-visible string (template literal) for the uncapped signal total (+${...}). UI i18n in this repo generally requires all user-facing text to come from translation keys, so this should be moved into a t(...) message (including the leading +) to keep localization consistent.

This issue also appears on line 754 of the same file.

expandTreeNode waited unconditionally on the search request that populates a
node's children. A node only fetches them the first time it opens, so a caller
re-expanding a node the tree already holds waits for a request that never
arrives — the full 30s waitForResponse default. The service-type drill-down
calls it inside a toPass({timeout: 60000}) retry, so two such iterations spend
the entire budget and the test fails with the tree still collapsed.

Return early when the node is already open, bound the response wait and tolerate
it never firing, then anchor on the switcher being open so the helper is correct
whether or not that click had to fetch. Bound the click and visibility wait in
the retry body too, so no single iteration can consume the whole budget.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gitar-bot

gitar-bot Bot commented Aug 15, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 4 resolved / 4 findings

Refactors search relevance ranking and analyzers to fix exact names losing to near matches, addressing all identified edge cases and query bugs. No issues found.

✅ 4 resolved
Performance: Every search now deserializes all hit sources to check identifiers

📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRankingHelper.java:704-710 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRankingHelper.java:719-730 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/elasticsearch/ElasticSearchSearchManager.java:1084-1096 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/opensearch/OpenSearchSearchManager.java:1130-1142
searchWithIdentifierPrecision evaluates hasPrunableFuzzyStage(searchSettings) && isExactIdentifierLookup(query, identifiersOf.apply(response)). The shipped default ranking contains a fuzzy stage plus non-fuzzy stages, so hasPrunableFuzzyStage is true for essentially every search, meaning hitIdentifiers runs on the result of EVERY doSearch — not just identifier lookups. It walks every hit and calls source.toJson().asJsonObject(), parsing each hit's source, work that is then duplicated by the later serializeSearchResponse/toJsonString. For large page sizes / deep pagination this adds redundant per-request parsing to the hot path. Consider extracting name/fqn from the already-materialized response or short-circuiting when the query has no whitespace/isn't a plausible identifier before converting all sources.

Quality: withoutFuzzyStages reference-identity memo never hits in production

📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRankingHelper.java:672-686
The memo in withoutFuzzyStages keys on reference identity (memo.source() == searchSettings) and its javadoc/test assume SettingsCache hands out one SearchSettings instance per version. In fact SettingsCache.getSetting calls JsonUtils.convertValue on every retrieval, returning a freshly deserialized instance per request (ElasticSearchSearchManager/OpenSearchSearchManager call getSetting per search). Since withoutFuzzyStages is invoked at most once per request (only on the second/precise pass), the memo never hits across requests and provides zero benefit — every exact-identifier lookup still pays a full JsonUtils.deepCopy of all asset configs. The unit test passes only because it deliberately reuses the same instance. Either drop the dead memo (it is misleading) or key it on the settings version rather than object identity.

Quality: Javadoc still claims ordinary searches cost one round-trip

📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRankingHelper.java:719-720 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/elasticsearch/ElasticSearchSearchManager.java:1069-1070
The javadoc on searchWithIdentifierPrecision (SearchRankingHelper.java:719-720) and on executeRankedSearch (ElasticSearchSearchManager.java:1069-1070 and the mirrored OpenSearchSearchManager block) still say "an ordinary search costs one round-trip ... only an exact identifier lookup pays a second." After this commit that only holds for the first page (from==0 && size>=IDENTITY_PROBE_SIZE); any deeper page now always issues a separate top-10 probe plus the requested window, so every paginated request beyond page one costs two round-trips regardless of whether it is an identifier lookup. Update these comments to describe the probe-per-page behavior so the doubled cost for deep pagination is not surprising to future readers.

Bug: Committed scratch test reads /tmp file and breaks CI

📄 openmetadata-service/src/test/java/org/openmetadata/service/search/ScratchDumpQueriesTest.java:24-38
ScratchDumpQueriesTest.dump() is debug scaffolding that reads its inputs from a hardcoded absolute path om_query_list.txt and writes serialized queries to om_queries. In CI (or any machine without that file) Files.readAllLines(Path.of("om_query_list.txt")) throws NoSuchFileException, failing the test and the build. This file is clearly a local debugging dump (class name "Scratch", no assertions, only side-effect writes) and should be deleted before merge rather than shipped.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 223 out of 226 changed files in this pull request and generated no new comments.

Suppressed comments (1)

openmetadata-spec/src/main/resources/elasticsearch/en/table_index_mapping.json:50

  • om_compound_analyzer still doesn’t apply the same stemming filters as om_analyzer (it only does word-delimiter + lowercase + flatten_graph). This keeps name.compound / displayName.compound out of sync with the base field, which can cause inconsistent matching and scoring for the same document depending on which subfield a ranking stage targets. If the intent is to fix the “compound analyzer did not stem” defect described in the PR, add om_stemmer and om_plural_stemmer to this analyzer’s filter chain (and apply the same change across the other index mappings that define om_compound_analyzer).

@sonarqubecloud

Copy link
Copy Markdown

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check To release Will cherry-pick this PR into the release branch

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

6 participants