From: Sarah Hoffmann Date: Tue, 28 Nov 2023 15:56:08 +0000 (+0100) Subject: add tests for interaction of category parameter with category terms X-Git-Tag: v4.4.0~75^2~1 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/25279d009a3d6aa0662a49fbde3d937775e26322 add tests for interaction of category parameter with category terms --- diff --git a/nominatim/api/search/db_search_builder.py b/nominatim/api/search/db_search_builder.py index a0018480..f89d8b62 100644 --- a/nominatim/api/search/db_search_builder.py +++ b/nominatim/api/search/db_search_builder.py @@ -90,6 +90,8 @@ class SearchBuilder: return near_items = self.get_near_items(assignment) + if near_items is not None and not near_items: + return # impossible compbination of near items and category parameter if assignment.name is None: if near_items and not sdata.postcodes: @@ -348,6 +350,9 @@ class SearchBuilder: tokens: Dict[Tuple[str, str], float] = {} for t in self.query.get_tokens(assignment.near_item, TokenType.NEAR_ITEM): cat = t.get_category() + # The category of a near search will be that of near_item. + # Thus, if search is restricted to a category parameter, + # the two sets must intersect. if (not self.details.categories or cat in self.details.categories)\ and t.penalty < tokens.get(cat, 1000.0): tokens[cat] = t.penalty diff --git a/test/python/api/search/test_db_search_builder.py b/test/python/api/search/test_db_search_builder.py index e3feff0d..87d75261 100644 --- a/test/python/api/search/test_db_search_builder.py +++ b/test/python/api/search/test_db_search_builder.py @@ -313,6 +313,64 @@ def test_name_only_search_with_category(): assert search.qualifiers.values == [('foo', 'bar')] +def test_name_with_near_item_search_with_category_mismatch(): + q = make_query([(1, TokenType.NEAR_ITEM, [(88, 'g')])], + [(2, TokenType.PARTIAL, [(1, 'a')]), + (2, TokenType.WORD, [(100, 'a')])]) + builder = SearchBuilder(q, SearchDetails.from_kwargs({'categories': [('foo', 'bar')]})) + + searches = list(builder.build(TokenAssignment(name=TokenRange(1, 2), + near_item=TokenRange(0, 1)))) + + assert len(searches) == 0 + + +def test_name_with_near_item_search_with_category_match(): + q = make_query([(1, TokenType.NEAR_ITEM, [(88, 'g')])], + [(2, TokenType.PARTIAL, [(1, 'a')]), + (2, TokenType.WORD, [(100, 'a')])]) + builder = SearchBuilder(q, SearchDetails.from_kwargs({'categories': [('foo', 'bar'), + ('this', 'that')]})) + + searches = list(builder.build(TokenAssignment(name=TokenRange(1, 2), + near_item=TokenRange(0, 1)))) + + assert len(searches) == 1 + search = searches[0] + + assert isinstance(search, dbs.NearSearch) + assert isinstance(search.search, dbs.PlaceSearch) + + +def test_name_with_qualifier_search_with_category_mismatch(): + q = make_query([(1, TokenType.QUALIFIER, [(88, 'g')])], + [(2, TokenType.PARTIAL, [(1, 'a')]), + (2, TokenType.WORD, [(100, 'a')])]) + builder = SearchBuilder(q, SearchDetails.from_kwargs({'categories': [('foo', 'bar')]})) + + searches = list(builder.build(TokenAssignment(name=TokenRange(1, 2), + qualifier=TokenRange(0, 1)))) + + assert len(searches) == 0 + + +def test_name_with_qualifier_search_with_category_match(): + q = make_query([(1, TokenType.QUALIFIER, [(88, 'g')])], + [(2, TokenType.PARTIAL, [(1, 'a')]), + (2, TokenType.WORD, [(100, 'a')])]) + builder = SearchBuilder(q, SearchDetails.from_kwargs({'categories': [('foo', 'bar'), + ('this', 'that')]})) + + searches = list(builder.build(TokenAssignment(name=TokenRange(1, 2), + qualifier=TokenRange(0, 1)))) + + assert len(searches) == 1 + search = searches[0] + + assert isinstance(search, dbs.PlaceSearch) + assert search.qualifiers.values == [('this', 'that')] + + def test_name_only_search_with_countries(): q = make_query([(1, TokenType.PARTIAL, [(1, 'a')]), (1, TokenType.WORD, [(100, 'a')])])