From: Sarah Hoffmann Date: Fri, 16 Nov 2018 22:52:19 +0000 (+0100) Subject: Add result ranking for missing housenumber and postcode X-Git-Tag: v3.3.0~74 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/9908c93d4cec91b5109d4fbc83dde18b5076350f?ds=inline;hp=--cc Add result ranking for missing housenumber and postcode Fixes #988. --- 9908c93d4cec91b5109d4fbc83dde18b5076350f diff --git a/lib/Geocode.php b/lib/Geocode.php index f0e03de5..e2fd7272 100644 --- a/lib/Geocode.php +++ b/lib/Geocode.php @@ -546,7 +546,6 @@ class Geocode // Do we have anything that looks like a lat/lon pair? $sQuery = $oCtx->setNearPointFromQuery($sQuery); - $aResults = array(); if ($sQuery || $this->aStructuredQuery) { // Start with a single blank search $aSearches = array(new SearchDescription($oCtx)); @@ -746,8 +745,10 @@ class Geocode // Start the search process $iGroupLoop = 0; $iQueryLoop = 0; + $aNextResults = array(); foreach ($aGroupedSearches as $iGroupedRank => $aSearches) { $iGroupLoop++; + $aResults = $aNextResults; foreach ($aSearches as $oSearch) { $iQueryLoop++; @@ -767,6 +768,23 @@ class Geocode if ($iQueryLoop > 20) break; } + if (!empty($aResults)) { + $aSplitResults = Result::splitResults($aResults); + Debug::printVar('Split results', $aSplitResults); + if ($iGroupLoop <= 4 && empty($aSplitResults['tail']) + && reset($aSplitResults['head'])->iResultRank > 0) { + // Haven't found an exact match for the query yet. + // Therefore add result from the next group level. + $aNextResults = $aSplitResults['head']; + foreach ($aNextResults as $oRes) { + $oRes->iResultRank--; + } + $aResults = array(); + } else { + $aResults = $aSplitResults['head']; + } + } + if (!empty($aResults) && ($this->iMinAddressRank != 0 || $this->iMaxAddressRank != 30)) { // Need to verify passes rank limits before dropping out of the loop (yuk!) // reduces the number of place ids, like a filter diff --git a/lib/Result.php b/lib/Result.php index d69ac62f..5c39f473 100644 --- a/lib/Result.php +++ b/lib/Result.php @@ -68,4 +68,32 @@ class Result return $sHousenumbers; } + + /** + * Split a result array into highest ranked result and the rest + * + * @param object[] $aResults List of results to split. + * + * @return array[] + */ + public static function splitResults($aResults) + { + $aHead = array(); + $aTail = array(); + $iMinRank = 10000; + + foreach ($aResults as $oRes) { + if ($oRes->iResultRank < $iMinRank) { + $aTail = array_merge($aTail, $aHead); + $aHead = array($oRes->iId => $oRes); + $iMinRank = $oRes->iResultRank; + } elseif ($oRes->iResultRank == $iMinRank) { + $aHead[$oRes->iId] = $oRes; + } else { + $aTail[$oRes->iId] = $oRes; + } + } + + return array('head' => $aHead, 'tail' => $aTail); + } } diff --git a/lib/SearchDescription.php b/lib/SearchDescription.php index ec14e546..204a7358 100644 --- a/lib/SearchDescription.php +++ b/lib/SearchDescription.php @@ -453,6 +453,9 @@ class SearchDescription if (empty($aResults) && $this->looksLikeFullAddress()) { $aResults = $aNamedPlaceIDs; + foreach ($aResults as $oRes) { + $oRes->iResultRank++; + } } } @@ -469,16 +472,13 @@ class SearchDescription if ($sPlaceIds) { $sSQL = 'SELECT place_id FROM placex'; $sSQL .= ' WHERE place_id in ('.$sPlaceIds.')'; - $sSQL .= " AND postcode = '".$this->sPostcode."'"; + $sSQL .= " AND postcode != '".$this->sPostcode."'"; Debug::printSQL($sSQL); $aFilteredPlaceIDs = chksql($oDB->getCol($sSQL)); if ($aFilteredPlaceIDs) { - $aNewResults = array(); foreach ($aFilteredPlaceIDs as $iPlaceId) { - $aNewResults[$iPlaceId] = $aResults[$iPlaceId]; + $aResults[$iPlaceId]->iResultRank++; } - $aResults = $aNewResults; - Debug::printVar('Place IDs after postcode filtering', $aResults); } } }