forked from organicmaps/organicmaps
[search] Suggest single-token categories.
This commit is contained in:
parent
8ff4fd19ad
commit
9906d541f6
6 changed files with 57 additions and 10 deletions
19
search/category_info.hpp
Normal file
19
search/category_info.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "../base/base.hpp"
|
||||
#include "../std/vector.hpp"
|
||||
|
||||
namespace search
|
||||
{
|
||||
|
||||
struct CategoryInfo
|
||||
{
|
||||
static uint32_t const DO_NOT_SUGGEST = 255;
|
||||
|
||||
CategoryInfo() : m_prefixLengthToSuggest(DO_NOT_SUGGEST) {}
|
||||
|
||||
vector<uint32_t> m_types;
|
||||
uint8_t m_prefixLengthToSuggest;
|
||||
};
|
||||
|
||||
} // namespace search
|
|
@ -21,6 +21,7 @@ HEADERS += \
|
|||
search_trie_matching.hpp \
|
||||
approximate_string_match.hpp \
|
||||
feature_offset_match.hpp \
|
||||
category_info.hpp \
|
||||
|
||||
SOURCES += \
|
||||
search_engine.cpp \
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "search_engine.hpp"
|
||||
#include "category_info.hpp"
|
||||
#include "result.hpp"
|
||||
#include "search_query.hpp"
|
||||
|
||||
|
@ -7,6 +8,7 @@
|
|||
|
||||
#include "../base/logging.hpp"
|
||||
|
||||
#include "../std/algorithm.hpp"
|
||||
#include "../std/function.hpp"
|
||||
#include "../std/string.hpp"
|
||||
#include "../std/vector.hpp"
|
||||
|
@ -16,20 +18,21 @@ namespace search
|
|||
{
|
||||
|
||||
Engine::Engine(IndexType const * pIndex, CategoriesHolder * pCategories)
|
||||
: m_pIndex(pIndex)
|
||||
: m_pIndex(pIndex), m_pCategories(new map<strings::UniString, CategoryInfo>())
|
||||
{
|
||||
for (CategoriesHolder::const_iterator it = pCategories->begin(); it != pCategories->end(); ++it)
|
||||
{
|
||||
for (size_t i = 0; i < it->m_synonyms.size(); ++i)
|
||||
{
|
||||
vector<uint32_t> & types = m_categories[NormalizeAndSimplifyString(it->m_synonyms[i].m_name)];
|
||||
types.insert(types.end(), it->m_types.begin(), it->m_types.end());
|
||||
CategoryInfo & info = (*m_pCategories)[NormalizeAndSimplifyString(it->m_synonyms[i].m_name)];
|
||||
info.m_types.insert(info.m_types.end(), it->m_types.begin(), it->m_types.end());
|
||||
info.m_prefixLengthToSuggest = min(info.m_prefixLengthToSuggest,
|
||||
it->m_synonyms[i].m_prefixLengthToSuggest);
|
||||
}
|
||||
}
|
||||
|
||||
delete pCategories;
|
||||
|
||||
m_pQuery.reset(new Query(pIndex, &m_categories));
|
||||
m_pQuery.reset(new Query(pIndex, m_pCategories.get()));
|
||||
}
|
||||
|
||||
Engine::~Engine()
|
||||
|
|
|
@ -19,6 +19,7 @@ class Index;
|
|||
namespace search
|
||||
{
|
||||
|
||||
class CategoryInfo;
|
||||
class Query;
|
||||
class Result;
|
||||
|
||||
|
@ -36,7 +37,7 @@ public:
|
|||
|
||||
private:
|
||||
Index const * m_pIndex;
|
||||
map<strings::UniString, vector<uint32_t> > m_categories;
|
||||
scoped_ptr<map<strings::UniString, CategoryInfo> > m_pCategories;
|
||||
scoped_ptr<search::Query> m_pQuery;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#include "search_query.hpp"
|
||||
#include "category_info.hpp"
|
||||
#include "feature_offset_match.hpp"
|
||||
#include "keyword_matcher.hpp"
|
||||
#include "latlon_match.hpp"
|
||||
#include "result.hpp"
|
||||
#include "../indexer/categories_holder.hpp"
|
||||
#include "search_common.hpp"
|
||||
#include "../indexer/feature_covering.hpp"
|
||||
#include "../indexer/features_vector.hpp"
|
||||
#include "../indexer/index.hpp"
|
||||
|
@ -137,6 +138,8 @@ void Query::Search(string const & query,
|
|||
}
|
||||
}
|
||||
|
||||
SuggestCategories();
|
||||
|
||||
SearchFeatures();
|
||||
|
||||
FlushResults(f);
|
||||
|
@ -264,8 +267,8 @@ void Query::SearchFeatures()
|
|||
CategoriesMapT::const_iterator it = m_pCategories->find(m_tokens[i]);
|
||||
if (it != m_pCategories->end())
|
||||
{
|
||||
for (size_t j = 0; j < it->second.size(); ++j)
|
||||
tokens[i].push_back(FeatureTypeToString(it->second[j]));
|
||||
for (size_t j = 0; j < it->second.m_types.size(); ++j)
|
||||
tokens[i].push_back(FeatureTypeToString(it->second.m_types[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,4 +284,22 @@ void Query::SearchFeatures()
|
|||
}
|
||||
}
|
||||
|
||||
void Query::SuggestCategories()
|
||||
{
|
||||
// Category matching.
|
||||
if (m_pCategories && !m_prefix.empty())
|
||||
{
|
||||
for (CategoriesMapT::const_iterator it = m_pCategories->begin();
|
||||
it != m_pCategories->end(); ++it)
|
||||
{
|
||||
if (it->second.m_prefixLengthToSuggest <= m_prefix.size() &&
|
||||
StartsWith(it->first.begin(), it->first.end(), m_prefix.begin(), m_prefix.end()))
|
||||
{
|
||||
string name = strings::ToUtf8(it->first);
|
||||
AddResult(impl::IntermediateResult(name, name + " ", it->second.m_prefixLengthToSuggest));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace search
|
||||
|
|
|
@ -17,13 +17,14 @@ class Index;
|
|||
namespace search
|
||||
{
|
||||
|
||||
class CategoryInfo;
|
||||
class KeywordMatcher;
|
||||
namespace impl { class IntermediateResult; struct FeatureLoader; class BestNameFinder; }
|
||||
|
||||
class Query
|
||||
{
|
||||
public:
|
||||
typedef map<strings::UniString, vector<uint32_t> > CategoriesMapT;
|
||||
typedef map<strings::UniString, CategoryInfo > CategoriesMapT;
|
||||
|
||||
Query(Index const * pIndex, CategoriesMapT const * pCategories);
|
||||
~Query();
|
||||
|
@ -45,6 +46,7 @@ private:
|
|||
void FlushResults(function<void (Result const &)> const & f);
|
||||
void UpdateViewportOffsets();
|
||||
void SearchFeatures();
|
||||
void SuggestCategories();
|
||||
void GetBestMatchName(FeatureType const & feature, uint32_t & penalty, string & name);
|
||||
|
||||
Index const * m_pIndex;
|
||||
|
|
Loading…
Add table
Reference in a new issue