diff options
author | Anatoly Serdtcev <serdtcev@maps.me> | 2019-02-01 16:42:33 +0300 |
---|---|---|
committer | Sergey Yershov <syershov@maps.me> | 2019-02-04 13:55:58 +0300 |
commit | faeee82dd69f54b3265d14a64f9cc985467ba0a9 (patch) | |
tree | 39fabef3723bf36f9a77d21eaf594f5c2f0f5074 /geocoder | |
parent | cf62483dc641d8d3ce59386e211b2463c7a69039 (diff) |
[geocoder] Search locality buildings
Diffstat (limited to 'geocoder')
-rw-r--r-- | geocoder/geocoder.cpp | 36 | ||||
-rw-r--r-- | geocoder/geocoder.hpp | 2 | ||||
-rw-r--r-- | geocoder/geocoder_tests/geocoder_tests.cpp | 19 | ||||
-rw-r--r-- | geocoder/index.cpp | 19 |
4 files changed, 54 insertions, 22 deletions
diff --git a/geocoder/geocoder.cpp b/geocoder/geocoder.cpp index 96c6b808bf..ae008bd693 100644 --- a/geocoder/geocoder.cpp +++ b/geocoder/geocoder.cpp @@ -287,30 +287,32 @@ void Geocoder::FillBuildingsLayer(Context & ctx, Tokens const & subquery, Layer { if (ctx.GetLayers().empty()) return; - auto const & layer = ctx.GetLayers().back(); - if (layer.m_type != Type::Street) - return; auto const & subqueryHN = MakeHouseNumber(subquery); if (!search::house_numbers::LooksLikeHouseNumber(subqueryHN, false /* isPrefix */)) return; - // We've already filled a street layer and now see something that resembles - // a house number. While it still can be something else (a zip code, for example) - // let's stay on the safer side and set the house number bit. - ctx.SetHouseNumberBit(); + for_each(ctx.GetLayers().rbegin(), ctx.GetLayers().rend(), [&, this] (auto const & layer) { + if (layer.m_type != Type::Street && layer.m_type != Type::Locality) + return; - for (auto const & streetDocId : layer.m_entries) - { - m_index.ForEachBuildingOnStreet(streetDocId, [&](Index::DocId const & buildingDocId) { - auto const & bld = m_index.GetDoc(buildingDocId); - auto const bt = static_cast<size_t>(Type::Building); - auto const & realHN = MakeHouseNumber(bld.m_address[bt]); - if (search::house_numbers::HouseNumbersMatch(realHN, subqueryHN, false /* queryIsPrefix */)) - curLayer.m_entries.emplace_back(buildingDocId); - }); - } + // We've already filled a street/location layer and now see something that resembles + // a house number. While it still can be something else (a zip code, for example) + // let's stay on the safer side and set the house number bit. + ctx.SetHouseNumberBit(); + + for (auto const & streetDocId : layer.m_entries) + { + m_index.ForEachBuildingOnStreet(streetDocId, [&](Index::DocId const & buildingDocId) { + auto const & bld = m_index.GetDoc(buildingDocId); + auto const bt = static_cast<size_t>(Type::Building); + auto const & realHN = MakeHouseNumber(bld.m_address[bt]); + if (search::house_numbers::HouseNumbersMatch(realHN, subqueryHN, false /* queryIsPrefix */)) + curLayer.m_entries.emplace_back(buildingDocId); + }); + } + }); } void Geocoder::FillRegularLayer(Context const & ctx, Type type, Tokens const & subquery, diff --git a/geocoder/geocoder.hpp b/geocoder/geocoder.hpp index 42fe749050..a829fbaa0f 100644 --- a/geocoder/geocoder.hpp +++ b/geocoder/geocoder.hpp @@ -55,7 +55,7 @@ public: BeamKey(base::GeoObjectId osmId, Type type, std::vector<Type> const & allTypes, bool allTokensUsed) : m_osmId(osmId) , m_type(type) - , m_allTypes(std::move(allTypes)) + , m_allTypes(allTypes) , m_allTokensUsed(allTokensUsed) { base::SortUnique(m_allTypes); diff --git a/geocoder/geocoder_tests/geocoder_tests.cpp b/geocoder/geocoder_tests/geocoder_tests.cpp index 58c951e9fa..c583598bbe 100644 --- a/geocoder/geocoder_tests/geocoder_tests.cpp +++ b/geocoder/geocoder_tests/geocoder_tests.cpp @@ -151,4 +151,23 @@ UNIT_TEST(Geocoder_MismatchedLocality) // "Street 3" looks almost like a match to "Paris-Street-3" but we should not emit it. TestGeocoder(geocoder, "Moscow Street 3", {}); } + +UNIT_TEST(Geocoder_LocalityBuilding) +{ + string const kData = R"#( +10 {"properties": {"address": {"locality": "Zelenograd"}}} + +22 {"properties": {"address": {"building": "2", "locality": "Zelenograd"}}} + +31 {"properties": {"address": {"street": "Street", "locality": "Zelenograd"}}} +32 {"properties": {"address": {"building": "2", "street": "Street", "locality": "Zelenograd"}}} +)#"; + + ScopedFile const regionsJsonFile("regions.jsonl", kData); + Geocoder geocoder(regionsJsonFile.GetFullPath()); + + base::GeoObjectId const building2(22); + + TestGeocoder(geocoder, "Zelenograd 2", {{building2, 1.0}}); +} } // namespace geocoder diff --git a/geocoder/index.cpp b/geocoder/index.cpp index 7602fd7777..e18a1ab6e1 100644 --- a/geocoder/index.cpp +++ b/geocoder/index.cpp @@ -99,13 +99,24 @@ void Index::AddHouses() if (buildingDoc.m_type != Type::Building) continue; - size_t const t = static_cast<size_t>(Type::Street); + auto const & street = buildingDoc.m_address[static_cast<size_t>(Type::Street)]; + auto const & locality = buildingDoc.m_address[static_cast<size_t>(Type::Locality)]; - ForEachDocId(buildingDoc.m_address[t], [&](DocId const & streetCandidate) { - auto const & streetDoc = GetDoc(streetCandidate); + Tokens const * buildingPlace = nullptr; + + if (!street.empty()) + buildingPlace = &street; + else if (!locality.empty()) + buildingPlace = &locality; + + if (!buildingPlace) + continue; + + ForEachDocId(*buildingPlace, [&](DocId const & placeCandidate) { + auto const & streetDoc = GetDoc(placeCandidate); if (streetDoc.IsParentTo(buildingDoc)) { - m_buildingsOnStreet[streetCandidate].emplace_back(docId); + m_buildingsOnStreet[placeCandidate].emplace_back(docId); ++numIndexed; if (numIndexed % kLogBatch == 0) |