mirror of
https://codeberg.org/comaps/comaps
synced 2026-01-03 03:13:48 +00:00
Organic Maps sources as of 02.04.2025 (fad26bbf22ac3da75e01e62aa01e5c8e11861005)
To expand with full Organic Maps and Maps.ME commits history run: git remote add om-historic [om-historic.git repo url] git fetch --tags om-historic git replace squashed-history historic-commits
This commit is contained in:
244
search/query_params.cpp
Normal file
244
search/query_params.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
#include "search/query_params.hpp"
|
||||
|
||||
#include "search/ranking_utils.hpp"
|
||||
#include "search/token_range.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
namespace search
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
// All synonyms should be lowercase.
|
||||
|
||||
/// @todo These should check the map language and use only the corresponding translation.
|
||||
map<string, vector<string>> const kSynonyms = {
|
||||
{"n", {"north"}},
|
||||
{"w", {"west"}},
|
||||
{"s", {"south"}},
|
||||
{"e", {"east"}},
|
||||
{"nw", {"northwest"}},
|
||||
{"ne", {"northeast"}},
|
||||
{"sw", {"southwest"}},
|
||||
{"se", {"southeast"}},
|
||||
|
||||
/// @todo Should not duplicate Street synonyms defined in StreetsSynonymsHolder (avoid useless double queries).
|
||||
/// Remove "street" and "avenue" here, but should update GetNameScore.
|
||||
{"st", {"saint", "street"}},
|
||||
{"dr", {"doctor"}},
|
||||
|
||||
// widely used in LATAM, like "Ntra Sra Asuncion Zelaya"
|
||||
{"ntra", {"nuestra"}},
|
||||
{"sra", {"senora"}},
|
||||
{"sta", {"santa"}},
|
||||
|
||||
{"al", {"allee", "alle"}},
|
||||
{"ave", {"avenue"}},
|
||||
/// @todo Should process synonyms with errors like "blvrd" -> "blvd".
|
||||
/// @see HouseOnStreetSynonymsWithMisprints test.
|
||||
{"blvd", {"boulevard"}},
|
||||
{"blvrd", {"boulevard"}},
|
||||
{"cir", {"circle"}},
|
||||
{"ct", {"court"}},
|
||||
{"hwy", {"highway"}},
|
||||
{"pl", {"place", "platz"}},
|
||||
{"rt", {"route"}},
|
||||
{"sq", {"square"}},
|
||||
|
||||
{"ал", {"аллея", "алея"}},
|
||||
{"бул", {"бульвар"}},
|
||||
{"зав", {"завулак"}},
|
||||
{"кв", {"квартал"}},
|
||||
{"наб", {"набережная", "набярэжная", "набережна"}},
|
||||
{"пер", {"переулок"}},
|
||||
{"пл", {"площадь", "площа"}},
|
||||
{"пр", {"проспект", "праспект", "провулок", "проезд", "праезд", "проїзд"}},
|
||||
{"туп", {"тупик", "тупік"}},
|
||||
{"ш", {"шоссе", "шаша", "шосе"}},
|
||||
|
||||
{"cd", {"caddesi"}},
|
||||
|
||||
{"св", {"святой", "святого", "святая", "святые", "святых", "свято"}},
|
||||
{"б", {"большая", "большой"}},
|
||||
{"бол", {"большая", "большой"}},
|
||||
{"м", {"малая", "малый"}},
|
||||
{"мал", {"малая", "малый"}},
|
||||
{"нов", {"новая", "новый"}},
|
||||
{"стар", {"старая", "старый"}},
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// QueryParams::Token ------------------------------------------------------------------------------
|
||||
void QueryParams::Token::AddSynonym(string const & s)
|
||||
{
|
||||
AddSynonym(strings::MakeUniString(s));
|
||||
}
|
||||
|
||||
void QueryParams::Token::AddSynonym(String const & s)
|
||||
{
|
||||
if (!IsStopWord(s))
|
||||
m_synonyms.push_back(s);
|
||||
}
|
||||
|
||||
string DebugPrint(QueryParams::Token const & token)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "Token [ m_original=" << DebugPrint(token.GetOriginal())
|
||||
<< ", m_synonyms=" << DebugPrint(token.m_synonyms) << " ]";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// QueryParams -------------------------------------------------------------------------------------
|
||||
void QueryParams::ClearStreetIndices()
|
||||
{
|
||||
class AdditionalCommonTokens
|
||||
{
|
||||
set<String> m_strings;
|
||||
public:
|
||||
AdditionalCommonTokens()
|
||||
{
|
||||
char const * arr[] = {
|
||||
"the", // English
|
||||
"der", "zum", "und", "auf", // German
|
||||
"del", "les", // Spanish
|
||||
"в", "на" // Cyrillic
|
||||
};
|
||||
for (char const * s : arr)
|
||||
m_strings.insert(NormalizeAndSimplifyString(s));
|
||||
}
|
||||
bool Has(String const & s) const { return m_strings.count(s) > 0; }
|
||||
};
|
||||
static AdditionalCommonTokens const s_addCommonTokens;
|
||||
|
||||
size_t const count = GetNumTokens();
|
||||
m_isCommonToken.resize(count, false);
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
auto const & token = GetToken(i).GetOriginal();
|
||||
if (IsStreetSynonym(token))
|
||||
{
|
||||
m_typeIndices[i].clear();
|
||||
m_isCommonToken[i] = true;
|
||||
}
|
||||
else if (s_addCommonTokens.Has(token))
|
||||
m_isCommonToken[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void QueryParams::Clear()
|
||||
{
|
||||
m_tokens.clear();
|
||||
m_prefixToken.Clear();
|
||||
m_hasPrefix = false;
|
||||
m_isCommonToken.clear();
|
||||
m_typeIndices.clear();
|
||||
m_langs.Clear();
|
||||
}
|
||||
|
||||
bool QueryParams::IsCategorySynonym(size_t i) const { return !GetTypeIndices(i).empty(); }
|
||||
|
||||
QueryParams::TypeIndices & QueryParams::GetTypeIndices(size_t i)
|
||||
{
|
||||
ASSERT_LESS(i, GetNumTokens(), ());
|
||||
return m_typeIndices[i];
|
||||
}
|
||||
|
||||
QueryParams::TypeIndices const & QueryParams::GetTypeIndices(size_t i) const
|
||||
{
|
||||
ASSERT_LESS(i, GetNumTokens(), ());
|
||||
return m_typeIndices[i];
|
||||
}
|
||||
|
||||
bool QueryParams::IsPrefixToken(size_t i) const
|
||||
{
|
||||
ASSERT_LESS(i, GetNumTokens(), ());
|
||||
return i == m_tokens.size();
|
||||
}
|
||||
|
||||
QueryParams::Token const & QueryParams::GetToken(size_t i) const
|
||||
{
|
||||
ASSERT_LESS(i, GetNumTokens(), ());
|
||||
return i < m_tokens.size() ? m_tokens[i] : m_prefixToken;
|
||||
}
|
||||
|
||||
QueryParams::Token & QueryParams::GetToken(size_t i)
|
||||
{
|
||||
ASSERT_LESS(i, GetNumTokens(), ());
|
||||
return i < m_tokens.size() ? m_tokens[i] : m_prefixToken;
|
||||
}
|
||||
|
||||
bool QueryParams::IsCommonToken(size_t i) const
|
||||
{
|
||||
return i < m_isCommonToken.size() && m_isCommonToken[i];
|
||||
}
|
||||
|
||||
bool QueryParams::IsNumberTokens(TokenRange const & range) const
|
||||
{
|
||||
ASSERT(range.IsValid(), (range));
|
||||
ASSERT_LESS_OR_EQUAL(range.End(), GetNumTokens(), ());
|
||||
|
||||
for (size_t i : range)
|
||||
{
|
||||
if (!GetToken(i).AnyOfOriginalOrSynonyms([](String const & s) { return strings::IsASCIINumeric(s); }))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QueryParams::RemoveToken(size_t i)
|
||||
{
|
||||
ASSERT_LESS(i, GetNumTokens(), ());
|
||||
if (i == m_tokens.size())
|
||||
{
|
||||
m_prefixToken.Clear();
|
||||
m_hasPrefix = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tokens.erase(m_tokens.begin() + i);
|
||||
}
|
||||
m_typeIndices.erase(m_typeIndices.begin() + i);
|
||||
}
|
||||
|
||||
void QueryParams::AddSynonyms()
|
||||
{
|
||||
for (auto & token : m_tokens)
|
||||
{
|
||||
string const ss = ToUtf8(MakeLowerCase(token.GetOriginal()));
|
||||
auto const it = kSynonyms.find(ss);
|
||||
if (it != kSynonyms.end())
|
||||
{
|
||||
for (auto const & synonym : it->second)
|
||||
token.AddSynonym(synonym);
|
||||
}
|
||||
}
|
||||
if (m_hasPrefix)
|
||||
{
|
||||
string const ss = ToUtf8(MakeLowerCase(m_prefixToken.GetOriginal()));
|
||||
auto const it = kSynonyms.find(ss);
|
||||
if (it != kSynonyms.end())
|
||||
{
|
||||
for (auto const & synonym : it->second)
|
||||
m_prefixToken.AddSynonym(synonym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string DebugPrint(QueryParams const & params)
|
||||
{
|
||||
ostringstream os;
|
||||
os << boolalpha << "QueryParams "
|
||||
<< "{ m_tokens: " << ::DebugPrint(params.m_tokens)
|
||||
<< ", m_prefixToken: " << DebugPrint(params.m_prefixToken)
|
||||
<< ", m_typeIndices: " << ::DebugPrint(params.m_typeIndices)
|
||||
<< ", m_langs: " << DebugPrint(params.m_langs)
|
||||
<< ", m_isCommonToken: " << ::DebugPrint(params.m_isCommonToken)
|
||||
<< " }";
|
||||
return os.str();
|
||||
}
|
||||
} // namespace search
|
||||
Reference in New Issue
Block a user