From 01c2c26160f602c867470eeeb8f8cd1184d3e85a Mon Sep 17 00:00:00 2001 From: Itz-Agasta Date: Sat, 9 May 2026 21:05:43 +0530 Subject: [PATCH] Improves geocoder reranking logic for locale-specific names - Refines how result labels are aggregated for reranking by using sets of localized names instead of concatenated strings. - Updates tests to reflect improved handling of locale-specific queries. --- src/nominatim_api/search/geocoder.py | 34 ++++++++----------- .../features/db/query/search_simple.feature | 6 ++++ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/nominatim_api/search/geocoder.py b/src/nominatim_api/search/geocoder.py index cbc64998..e67a278e 100644 --- a/src/nominatim_api/search/geocoder.py +++ b/src/nominatim_api/search/geocoder.py @@ -7,7 +7,7 @@ """ Public interface to the search code. """ -from typing import List, Any, Optional, Iterator, Tuple, Dict +from typing import List, Any, Optional, Iterator, Tuple, Dict, Set import itertools import re import difflib @@ -175,27 +175,25 @@ class ForwardGeocoder: return final - def _get_result_rerank_text(self, result: SearchResult) -> str: + def _get_result_rerank_text(self, result: SearchResult) -> Set[str]: if not self.params.locales: - return result.display_name or '' + return {result.display_name} if result.display_name else set() - label_parts: List[str] = [] + label_parts: Set[str] = set() if result.address_rows: for line in result.address_rows: if line.isaddress and line.names: address_name = self.params.locales.display_name(line.names) - if address_name and ( - not label_parts or label_parts[-1] != address_name - ): - label_parts.append(address_name) + if address_name: + label_parts.add(address_name) if label_parts: - return ', '.join(label_parts) + return label_parts if result.names: - return self.params.locales.display_name(result.names) + return {self.params.locales.display_name(result.names)} - return result.display_name or '' + return {result.display_name} if result.display_name else set() def rerank_by_query(self, query: QueryStruct, results: SearchResults) -> None: """ Adjust the accuracy of the localized result according to how well @@ -218,7 +216,7 @@ class ForwardGeocoder: # (e.g., name:en) are included in the match pool. rerank_text = self._get_result_rerank_text(result) norm = self.query_analyzer.normalize_text( - ' '.join((rerank_text, result.country_code or '')) + ' '.join((*rerank_text, result.country_code or '')) ) words = set((w for w in re.split('[-,: ]+', norm) if w)) if not words: @@ -233,13 +231,11 @@ class ForwardGeocoder: # to offset this. if result.rank_address == 4: if self.params.locales and result.names: - loc_names = [result.names[t] for t in self.params.locales.name_tags - if t in result.names] - if loc_names: - norm_loc = self.query_analyzer.normalize_text(' '.join(loc_names)) - loc_words = set(w for w in re.split('[-,: ]+', norm_loc) if w) - if loc_words and loc_words.isdisjoint(qwords): - result.accuracy += result.calculated_importance() * 0.5 + # Exclude country code from disjoint check + check_words = (words - {result.country_code.lower()}) \ + if result.country_code else words + if check_words and check_words.isdisjoint(qwords): + result.accuracy += result.calculated_importance() * 0.5 else: distance *= 2 result.accuracy += distance * 0.3 / sum(len(w) for w in qwords) diff --git a/test/bdd/features/db/query/search_simple.feature b/test/bdd/features/db/query/search_simple.feature index 8ff6a44b..5f7a1fbb 100644 --- a/test/bdd/features/db/query/search_simple.feature +++ b/test/bdd/features/db/query/search_simple.feature @@ -114,3 +114,9 @@ Feature: Searching of simple objects Then result 0 contains | object | | N1 | + When geocoding "Athens" + | accept-language | + | de | + Then result 0 contains + | object | + | N2 | -- 2.47.3