From 15a215729eec7353254fc42972532ce3f38d743a Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Tue, 19 Sep 2017 00:07:11 +0200 Subject: [PATCH] fix handling of near queries with special search Make sure to use the classtype tables with near search and allow to search for arbitrary key/values (forbidding it for viewbox searches). Add tests for near queries. --- lib/Geocode.php | 37 ++++++++++++----------------- test/bdd/api/search/params.feature | 8 ++++++- test/bdd/api/search/queries.feature | 12 ++++++++++ 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/lib/Geocode.php b/lib/Geocode.php index 314d20bc..a5b9d485 100644 --- a/lib/Geocode.php +++ b/lib/Geocode.php @@ -1274,8 +1274,8 @@ class Geocode } // No location term? - if (!sizeof($aSearch['aName']) && !sizeof($aSearch['aAddress']) && !$aSearch['oNear']) { - if ($aSearch['sCountryCode'] && !$aSearch['sClass'] && !$aSearch['sHouseNumber']) { + if (!sizeof($aSearch['aName']) && !sizeof($aSearch['aAddress'])) { + if ($aSearch['sCountryCode'] && !$aSearch['sClass'] && !$aSearch['sHouseNumber'] && !$aSearch['oNear']) { // Just looking for a country by code - look it up if (4 >= $this->iMinAddressRank && 4 <= $this->iMaxAddressRank) { $sSQL = "SELECT place_id FROM placex WHERE country_code='".$aSearch['sCountryCode']."' AND rank_search = 4"; @@ -1295,39 +1295,32 @@ class Geocode if (chksql($this->oDB->getOne($sSQL))) { $sSQL = "SELECT place_id FROM place_classtype_".$aSearch['sClass']."_".$aSearch['sType']." ct"; if ($sCountryCodesSQL) $sSQL .= " JOIN placex USING (place_id)"; - $sSQL .= " WHERE st_contains($this->sViewboxSmallSQL, ct.centroid)"; + if ($aSearch['oNear']) { + $sSQL .= " WHERE ".$aSearch['oNear']->withinSQL('ct.centroid'); + } else { + $sSQL .= " WHERE st_contains($this->sViewboxSmallSQL, ct.centroid)"; + } if ($sCountryCodesSQL) $sSQL .= " AND country_code in ($sCountryCodesSQL)"; if (sizeof($this->aExcludePlaceIDs)) { $sSQL .= " AND place_id not in (".join(',', $this->aExcludePlaceIDs).")"; } - if ($this->sViewboxCentreSQL) $sSQL .= " ORDER BY ST_Distance($this->sViewboxCentreSQL, ct.centroid) ASC"; + if ($this->sViewboxCentreSQL) { + $sSQL .= " ORDER BY ST_Distance($this->sViewboxCentreSQL, ct.centroid) ASC"; + } elseif ($aSearch['oNear']) { + $sSQL .= " ORDER BY ".$aSearch['oNear']->distanceSQL('ct.centroid').' ASC'; + } $sSQL .= " limit $this->iLimit"; if (CONST_Debug) var_dump($sSQL); $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); - - // If excluded place IDs are given, it is fair to assume that - // there have been results in the small box, so no further - // expansion in that case. - // Also don't expand if bounded results were requested. - if (!sizeof($aPlaceIDs) && !sizeof($this->aExcludePlaceIDs) && !$this->bBoundedSearch) { - $sSQL = "SELECT place_id FROM place_classtype_".$aSearch['sClass']."_".$aSearch['sType']." ct"; - if ($sCountryCodesSQL) $sSQL .= " join placex using (place_id)"; - $sSQL .= " WHERE ST_Contains($this->sViewboxLargeSQL, ct.centroid)"; - if ($sCountryCodesSQL) $sSQL .= " AND country_code in ($sCountryCodesSQL)"; - if ($this->sViewboxCentreSQL) $sSQL .= " ORDER BY ST_Distance($this->sViewboxCentreSQL, ct.centroid) ASC"; - $sSQL .= " LIMIT $this->iLimit"; - if (CONST_Debug) var_dump($sSQL); - $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); - } - } else { + } else if ($aSearch['oNear']) { $sSQL = "SELECT place_id "; $sSQL .= "FROM placex "; $sSQL .= "WHERE class='".$aSearch['sClass']."' "; $sSQL .= " AND type='".$aSearch['sType']."'"; - $sSQL .= " AND ST_Contains($this->sViewboxSmallSQL, geometry) "; + $sSQL .= " AND ".$aSearch['oNear']->withinSQL('geometry'); $sSQL .= " AND linked_place_id is null"; if ($sCountryCodesSQL) $sSQL .= " AND country_code in ($sCountryCodesSQL)"; - if ($this->sViewboxCentreSQL) $sSQL .= " ORDER BY ST_Distance($this->sViewboxCentreSQL, centroid) ASC"; + $sSQL .= " ORDER BY ".$aSearch['oNear']->distanceSQL('centroid')." ASC"; $sSQL .= " LIMIT $this->iLimit"; if (CONST_Debug) var_dump($sSQL); $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); diff --git a/test/bdd/api/search/params.feature b/test/bdd/api/search/params.feature index c1318a62..d8423592 100644 --- a/test/bdd/api/search/params.feature +++ b/test/bdd/api/search/params.feature @@ -73,6 +73,12 @@ Feature: Search queries | city | | Montevideo | + Scenario: Country search with bounded viewbox remain in the area + When sending json search query "" with address + | bounded | viewbox | country | + | 1 | -56.16786,-34.84061,-56.12525,-34.86526 | de | + Then less than 1 result is returned + Scenario: Search with bounded viewboxlbrt in right area When sending json search query "bar" with address | bounded | viewboxlbrt | @@ -90,7 +96,7 @@ Feature: Search queries | ^[^,]*[Rr]estaurant.* | Scenario: bounded search remains within viewbox, even with no results - When sending json search query "restaurant" + When sending json search query "[restaurant]" | bounded | viewbox | | 1 | 43.5403125,-5.6563282,43.54285,-5.662003 | Then less than 1 result is returned diff --git a/test/bdd/api/search/queries.feature b/test/bdd/api/search/queries.feature index ccfeac40..49e1d9c0 100644 --- a/test/bdd/api/search/queries.feature +++ b/test/bdd/api/search/queries.feature @@ -84,6 +84,18 @@ Feature: Search queries | class | type | | amenity | place_of_worship | + Scenario: POI search near given coordinate + When sending json search query "restaurant near 47.16712,9.51100" + Then results contain + | class | type | + | amenity | restaurant | + + Scenario: Arbitrary key/value search near given coordinate + When sending json search query "[man_made=mast] 47.15739,9.61264" + Then results contain + | class | type | + | man_made | mast | + # https://trac.openstreetmap.org/ticket/5094 Scenario: housenumbers are ordered by complete match first When sending json search query "6395 geminis, montevideo" with address -- 2.39.5