diff --git a/search/geocoder.cpp b/search/geocoder.cpp index ffc2f9e58f..182e038269 100644 --- a/search/geocoder.cpp +++ b/search/geocoder.cpp @@ -585,7 +585,7 @@ void Geocoder::GoImpl(vector> const & infos, bool inViewport auto const mwmType = m_context->GetType(); CHECK(mwmType, ()); if (mwmType->m_viewportIntersected || mwmType->m_containsUserPosition || - m_preRanker.Size() == 0) + !m_preRanker.HaveFullResult()) { MatchAroundPivot(ctx); } diff --git a/search/pre_ranker.hpp b/search/pre_ranker.hpp index ab0dc4c19c..ee6b6e87ae 100644 --- a/search/pre_ranker.hpp +++ b/search/pre_ranker.hpp @@ -72,6 +72,8 @@ public: return; m_results.emplace_back(std::forward(args)...); + if (m_results.back().GetInfo().m_allTokensUsed) + m_haveFullResult = true; } // Computes missing fields for all pre-results. @@ -86,6 +88,7 @@ public: size_t Size() const { return m_results.size(); } size_t BatchSize() const { return m_params.m_batchSize; } size_t NumSentResults() const { return m_numSentResults; } + bool HaveFullResult() const { return m_haveFullResult; } size_t Limit() const { return m_params.m_limit; } template @@ -110,6 +113,8 @@ private: // Amount of results sent up the pipeline. size_t m_numSentResults = 0; + bool m_haveFullResult = false; + // Cache of nested rects used to estimate distance from a feature to the pivot. NestedRectsCache m_pivotFeatures; diff --git a/search/search_integration_tests/processor_test.cpp b/search/search_integration_tests/processor_test.cpp index b290caa021..abd58c0cbc 100644 --- a/search/search_integration_tests/processor_test.cpp +++ b/search/search_integration_tests/processor_test.cpp @@ -2792,5 +2792,40 @@ UNIT_CLASS_TEST(ProcessorTest, MatchedFraction) TEST(ResultsMatch("8 ", rules), ()); } } + +UNIT_CLASS_TEST(ProcessorTest, AvoidMathcAroundPivotInMwmWithCity) +{ + string const minskCountryName = "Minsk"; + + TestCity minsk(m2::PointD(-10.0, -10.0), "Minsk", "en", 10 /* rank */); + // World.mwm should intersect viewport. + TestPOI dummy(m2::PointD(10.0, 10.0), "", "en"); + + auto worldId = BuildWorld([&](TestMwmBuilder & builder) { + builder.Add(minsk); + builder.Add(dummy); + }); + + TestCafe minskCafe(m2::PointD(-9.99, -9.99), "Minsk cafe", "en"); + auto minskId = BuildCountry(minskCountryName, [&](TestMwmBuilder & builder) { + builder.Add(minsk); + builder.Add(minskCafe); + }); + + SetViewport(m2::RectD(m2::PointD(-1.0, -1.0), m2::PointD(1.0, 1.0))); + { + // Minsk cafe should not appear here because we have (worldId, minsk) result with all tokens + // used. + Rules rules = {ExactMatch(worldId, minsk)}; + TEST(ResultsMatch("Minsk ", rules), ()); + TEST(ResultsMatch("Minsk", rules), ()); + } + { + // We search for pois until we find result with all tokens used. We do not emit relaxed result + // from world. + Rules rules = {ExactMatch(minskId, minskCafe)}; + TEST(ResultsMatch("Minsk cafe", rules), ()); + } +} } // namespace } // namespace search