From cab2a74740ba951a09635c0ca65ead65a8b2f361 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Sat, 12 Aug 2023 16:12:44 +0200 Subject: [PATCH] do not use index when searching in large areas This concerns viewboxes as well as radius search. --- nominatim/api/search/db_searches.py | 11 +++++++++-- nominatim/api/search/geocoder.py | 3 ++- nominatim/api/search/token_assignment.py | 2 ++ nominatim/db/sqlalchemy_types.py | 10 +++++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/nominatim/api/search/db_searches.py b/nominatim/api/search/db_searches.py index 77d9f848..02a45e7c 100644 --- a/nominatim/api/search/db_searches.py +++ b/nominatim/api/search/db_searches.py @@ -622,7 +622,10 @@ class PlaceSearch(AbstractSearch): if details.viewbox is not None: if details.bounded_viewbox: - sql = sql.where(tsearch.c.centroid.intersects(VIEWBOX_PARAM)) + if details.viewbox.area < 0.2: + sql = sql.where(tsearch.c.centroid.intersects(VIEWBOX_PARAM)) + else: + sql = sql.where(tsearch.c.centroid.ST_Intersects_no_index(VIEWBOX_PARAM)) else: penalty += sa.case((t.c.geometry.intersects(VIEWBOX_PARAM), 0.0), (t.c.geometry.intersects(VIEWBOX2_PARAM), 1.0), @@ -630,7 +633,11 @@ class PlaceSearch(AbstractSearch): if details.near is not None: if details.near_radius is not None: - sql = sql.where(tsearch.c.centroid.ST_DWithin(NEAR_PARAM, NEAR_RADIUS_PARAM)) + if details.near_radius < 0.1: + sql = sql.where(tsearch.c.centroid.ST_DWithin(NEAR_PARAM, NEAR_RADIUS_PARAM)) + else: + sql = sql.where(tsearch.c.centroid.ST_DWithin_no_index(NEAR_PARAM, + NEAR_RADIUS_PARAM)) sql = sql.add_columns(-tsearch.c.centroid.ST_Distance(NEAR_PARAM) .label('importance')) sql = sql.order_by(sa.desc(sa.text('importance'))) diff --git a/nominatim/api/search/geocoder.py b/nominatim/api/search/geocoder.py index 311840a9..564e3d8d 100644 --- a/nominatim/api/search/geocoder.py +++ b/nominatim/api/search/geocoder.py @@ -152,7 +152,8 @@ class ForwardGeocoder: # pylint: disable=invalid-name,too-many-locals def _dump_searches(searches: List[AbstractSearch], query: QueryStruct, start: int = 0) -> Iterator[Optional[List[Any]]]: - yield ['Penalty', 'Lookups', 'Housenr', 'Postcode', 'Countries', 'Qualifier', 'Catgeory', 'Rankings'] + yield ['Penalty', 'Lookups', 'Housenr', 'Postcode', 'Countries', + 'Qualifier', 'Catgeory', 'Rankings'] def tk(tl: List[int]) -> str: tstr = [f"{query.find_lookup_word_by_id(t)}({t})" for t in tl] diff --git a/nominatim/api/search/token_assignment.py b/nominatim/api/search/token_assignment.py index 0ae2cd43..3f0e737b 100644 --- a/nominatim/api/search/token_assignment.py +++ b/nominatim/api/search/token_assignment.py @@ -253,6 +253,8 @@ class _TokenSequence: priors = sum(1 for t in self.seq[hnrpos+1:] if t.ttype == qmod.TokenType.PARTIAL) if not self._adapt_penalty_from_priors(priors, 1): return False + if any(t.ttype == qmod.TokenType.CATEGORY for t in self.seq): + self.penalty += 1.0 return True diff --git a/nominatim/db/sqlalchemy_types.py b/nominatim/db/sqlalchemy_types.py index 7d3789aa..9e1f9fce 100644 --- a/nominatim/db/sqlalchemy_types.py +++ b/nominatim/db/sqlalchemy_types.py @@ -66,7 +66,15 @@ class Geometry(types.UserDefinedType): # type: ignore[type-arg] def ST_DWithin(self, other: SaColumn, distance: SaColumn) -> SaColumn: - return sa.func.ST_DWithin(self, other, distance, type_=sa.Float) + return sa.func.ST_DWithin(self, other, distance, type_=sa.Boolean) + + + def ST_DWithin_no_index(self, other: SaColumn, distance: SaColumn) -> SaColumn: + return sa.func._ST_DWithin(self, other, distance, type_=sa.Boolean) + + + def ST_Intersects_no_index(self, other: SaColumn) -> SaColumn: + return sa.func._ST_Intersects(self, other, type_=sa.Boolean) def ST_Distance(self, other: SaColumn) -> SaColumn: