Repository navigation
Make v2 search case- and accent-insensitive - #592
Merged
Merged
Conversation
Add folding_normalizer (lowercase + asciifolding) to v2 keyword fields, use string_lowercase for names.value and relationships.label, aggregate on un-normalized .raw subfields, and NFC-normalize query input. Refs ror-community/ror-roadmap#175, ror-community/ror-roadmap#398 Co-authored-by: Joseph Rhoads <jrhoads@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The mapping migration requires a coordinated production reindex, and its integration coverage is not exercised by CI.
Review effort: Balanced
Findings: None
What changed in this PR
Makes v2 search case-, accent-, and Unicode-normalization-insensitive while preserving facet casing.
Changes:
- Adds folding normalizers and raw aggregation fields.
- NFC-normalizes query and filter input.
- Adds unit and integration coverage.
| File | Description |
|---|---|
rorapi/v2/index_template_es7.json |
Configures normalized search fields and raw facet fields. |
rorapi/common/queries.py |
Normalizes input and targets raw aggregations. |
rorapi/tests/tests_unit/tests_queries_v2.py |
Tests normalization and aggregation fields. |
rorapi/tests/tests_integration/tests_search_v2.py |
Tests case/accent equivalence and facet casing. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Make v2 advanced (and bare-term) search case- and accent-insensitive, fixing ror-community/ror-roadmap#175 and ror-community/ror-roadmap#398 in one change.
Today
query.advancedis aquery_stringoverdefault_field="*". Most v2 keyword fields have no normalizer (exact-byte matching), andnames.value/relationships.labeluse thestandardanalyzer (lowercase only, no accent folding). That makes queries likedenvervsDenver,relationships.type:childvsChild, andHuevsHuế/Universite de MontrealvsUniversité de Montréalmiss.Approach
Normalize keyword fields at index time with a shared
folding_normalizer(lowercase + asciifolding), switch the main analyzers onnames.valueandrelationships.labelto the existingstring_lowercaseanalyzer, NFC-normalize query/filter input in Python, and aggregate on un-normalized.rawsubfields so facet keys keep their original casing.Key Modifications
rorapi/v2/index_template_es7.jsonanalysis.normalizer.folding_normalizer(lowercase+asciifolding).locations.geonames_details.{name,country_name,country_code,continent_name,continent_code,country_subdivision_name,country_subdivision_code},types,status,relationships.type,names.lang,names.types,links.type,external_ids.type. Leaveid,external_ids.all,external_ids.preferred, dates, and numbers untouched.types,status,country_code,continent_code) afields.raw: {type: keyword}subfield.names.valueandrelationships.labelmain analyzer tostring_lowercase(keep.keyword/.normsubfields).rorapi/common/queries.pyquery,query.advanced, and filter values before building the ES query.types.raw,locations.geonames_details.country_code.raw,locations.geonames_details.continent_code.raw, andstatus.raw..rawaggregations and NFC normalization of query/filter input.Important Technical Details
createindex, thenindexror/indexrordump) together with the deploy. Until then, the new*.rawaggregation fields will not exist (facets empty on the old index) and search behavior will not change..raw.run_tests.ymlonly runstests_unit); they need an index built from the current template.Types of changes
Reviewer, please remember our guidelines:
Test plan
test-pr / testandflow-guardpass;ruffsoft-fails repo-wide withcontinue-on-error, unrelated to this change)rorapi.tests.tests_unit) pass locally aside from pre-existingtest_heartbeat_successwithout MySQLdenver/Denver,relationships.type:child/Child,stellenbosch/Stellenbosch,Hue/Huế,Montreal/Montréal, NFD vs NFCHuế, andnames.value:"Universite de Montreal"return matching results; facet titles keep original casing. The new integration tests fail against the old template and pass against the new one.tests_search_v2.py, then repeat on prod