Introduce SearchInfo.

SearchInfo is a small helper structure to store information about the
queried search. It regroup already existing information (`patternString`,
geo query, ...) in one structure.
It is also used as key in the cache instead of using a generated string.
This commit is contained in:
Matthieu Gautier 2022-03-09 14:45:22 +01:00
parent e7293346be
commit d740ffe465
2 changed files with 146 additions and 94 deletions

View File

@ -109,6 +109,55 @@ unsigned int getCacheLength(const char* name, unsigned int defaultVal) {
} }
} // unnamed namespace } // unnamed namespace
SearchInfo::SearchInfo(const std::string& pattern)
: pattern(pattern),
geoQuery()
{}
SearchInfo::SearchInfo(const std::string& pattern, GeoQuery geoQuery)
: pattern(pattern),
geoQuery(geoQuery)
{}
SearchInfo::SearchInfo(const RequestContext& request)
: pattern(request.get_optional_param<std::string>("pattern", "")),
geoQuery(),
bookName(request.get_optional_param<std::string>("content", ""))
{
/* Retrive geo search */
try {
auto latitude = request.get_argument<float>("latitude");
auto longitude = request.get_argument<float>("longitude");
auto distance = request.get_argument<float>("distance");
geoQuery = GeoQuery(latitude, longitude, distance);
} catch(const std::out_of_range&) {}
catch(const std::invalid_argument&) {}
if (!geoQuery && pattern.empty()) {
throw std::invalid_argument("No query provided.");
}
}
zim::Query SearchInfo::getZimQuery(bool verbose) const {
zim::Query query;
if(pattern.empty()) {
// Execute geo-search
if (verbose) {
cout << "Performing geo query `" << geoQuery.distance << "&(" << geoQuery.latitude << ";" << geQuery.longitude << ")'" << endl;
}
query.setQuery("");
query.setGeorange(geoQuery.latitude, geoQuery.longitude, geoQuery.distance);
} else {
// Execute Ft search
if (verbose) {
cout << "Performing query `" << pattern << "'" << endl;
}
query.setQuery(pattern);
}
return query;
}
static IdNameMapper defaultNameMapper; static IdNameMapper defaultNameMapper;
static MHD_Result staticHandlerCallback(void* cls, static MHD_Result staticHandlerCallback(void* cls,
@ -499,48 +548,26 @@ std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& re
printf("** running handle_search\n"); printf("** running handle_search\n");
} }
std::string patternString;
try { try {
patternString = request.get_argument("pattern"); auto searchInfo = SearchInfo(request);
} catch (const std::out_of_range&) {}
/* Retrive geo search */ std::string bookId;
bool has_geo_query = false;
float latitude = 0;
float longitude = 0;
float distance = 0;
try {
latitude = request.get_argument<float>("latitude");
longitude = request.get_argument<float>("longitude");
distance = request.get_argument<float>("distance");
has_geo_query = true;
} catch(const std::out_of_range&) {}
catch(const std::invalid_argument&) {}
std::string bookName, bookId;
std::shared_ptr<zim::Archive> archive; std::shared_ptr<zim::Archive> archive;
if (!searchInfo.bookName.empty()) {
try { try {
bookName = request.get_argument("content"); bookId = mp_nameMapper->getIdForName(searchInfo.bookName);
bookId = mp_nameMapper->getIdForName(bookName);
archive = mp_library->getArchiveById(bookId); archive = mp_library->getArchiveById(bookId);
} catch (const std::out_of_range&) {} } catch (const std::out_of_range&) {
/* Make the search */
if (patternString.empty() && ! has_geo_query) {
return HTTP400HtmlResponse(*this, request)
+ invalidUrlMsg
+ std::string("No query provided.");
}
if (!archive && !bookName.empty()) {
auto data = get_default_data(); auto data = get_default_data();
data.set("pattern", encodeDiples(patternString)); data.set("pattern", encodeDiples(searchInfo.pattern));
data.set("root", m_root); data.set("root", m_root);
auto response = ContentResponse::build(*this, RESOURCE::templates::no_search_result_html, data, "text/html; charset=utf-8"); auto response = ContentResponse::build(*this, RESOURCE::templates::no_search_result_html, data, "text/html; charset=utf-8");
response->set_code(MHD_HTTP_NOT_FOUND); response->set_code(MHD_HTTP_NOT_FOUND);
return withTaskbarInfo(bookName, archive.get(), std::move(response)); return withTaskbarInfo(searchInfo.bookName, archive.get(), std::move(response));
}
} }
/* Make the search */
std::shared_ptr<zim::Searcher> searcher; std::shared_ptr<zim::Searcher> searcher;
if (archive) { if (archive) {
searcher = searcherCache.getOrPut(bookId, [=](){ return std::make_shared<zim::Searcher>(*archive);}); searcher = searcherCache.getOrPut(bookId, [=](){ return std::make_shared<zim::Searcher>(*archive);});
@ -574,41 +601,22 @@ std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& re
} }
/* Get the results */ /* Get the results */
std::string queryString;
try {
zim::Query query;
if (patternString.empty()) {
// Execute geo-search
if (m_verbose.load()) {
cout << "Performing geo query `" << distance << "&(" << latitude << ";" << longitude << ")'" << endl;
}
query.setQuery("");
queryString = "GEO:" + to_string(latitude) + to_string(longitude) + to_string(distance);
query.setGeorange(latitude, longitude, distance);
} else {
// Execute Ft search
if (m_verbose.load()) {
cout << "Performing query `" << patternString << "'" << endl;
}
queryString = "FT:" + removeAccents(patternString);
query.setQuery(queryString);
}
queryString = bookId + queryString;
std::shared_ptr<zim::Search> search; std::shared_ptr<zim::Search> search;
search = searchCache.getOrPut(queryString, [=](){ return make_shared<zim::Search>(searcher->search(query));}); search = searchCache.getOrPut(searchInfo, [=](){ return make_shared<zim::Search>(searcher->search(searchInfo.getZimQuery(m_verbose.load())));});
SearchRenderer renderer(search->getResults(start, pageLength), mp_nameMapper, mp_library, start, SearchRenderer renderer(search->getResults(start, pageLength), mp_nameMapper, mp_library, start,
search->getEstimatedMatches()); search->getEstimatedMatches());
renderer.setSearchPattern(patternString); renderer.setSearchPattern(searchInfo.pattern);
renderer.setSearchContent(bookName); renderer.setSearchContent(searchInfo.bookName);
renderer.setProtocolPrefix(m_root + "/"); renderer.setProtocolPrefix(m_root + "/");
renderer.setSearchProtocolPrefix(m_root + "/search?"); renderer.setSearchProtocolPrefix(m_root + "/search?");
renderer.setPageLength(pageLength); renderer.setPageLength(pageLength);
auto response = ContentResponse::build(*this, renderer.getHtml(), "text/html; charset=utf-8"); auto response = ContentResponse::build(*this, renderer.getHtml(), "text/html; charset=utf-8");
return withTaskbarInfo(bookName, archive.get(), std::move(response)); return withTaskbarInfo(searchInfo.bookName, archive.get(), std::move(response));
} catch (const std::invalid_argument& e) {
return HTTP400HtmlResponse(*this, request)
+ invalidUrlMsg
+ std::string(e.what());
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return Response::build_500(*this, e.what()); return Response::build_500(*this, e.what());

View File

@ -43,9 +43,53 @@ extern "C" {
namespace kiwix { namespace kiwix {
struct GeoQuery {
GeoQuery()
: GeoQuery(0, 0, -1)
{}
GeoQuery(float latitude, float longitude, float distance)
: latitude(latitude), longitude(longitude), distance(distance)
{}
float latitude;
float longitude;
float distance;
explicit operator bool() const {
return distance >= 0;
}
friend bool operator<(const GeoQuery& l, const GeoQuery& r)
{
return std::tie(l.latitude, l.longitude, l.distance)
< std::tie(r.latitude, r.longitude, r.distance); // keep the same order
}
};
class SearchInfo {
public:
SearchInfo(const std::string& pattern);
SearchInfo(const std::string& pattern, GeoQuery geoQuery);
SearchInfo(const RequestContext& request);
zim::Query getZimQuery(bool verbose) const;
friend bool operator<(const SearchInfo& l, const SearchInfo& r)
{
return std::tie(l.bookName, l.pattern, l.geoQuery)
< std::tie(r.bookName, r.pattern, r.geoQuery); // keep the same order
}
public: //data
std::string pattern;
GeoQuery geoQuery;
std::string bookName;
};
typedef kainjow::mustache::data MustacheData; typedef kainjow::mustache::data MustacheData;
typedef ConcurrentCache<string, std::shared_ptr<zim::Searcher>> SearcherCache; typedef ConcurrentCache<string, std::shared_ptr<zim::Searcher>> SearcherCache;
typedef ConcurrentCache<string, std::shared_ptr<zim::Search>> SearchCache; typedef ConcurrentCache<SearchInfo, std::shared_ptr<zim::Search>> SearchCache;
typedef ConcurrentCache<string, std::shared_ptr<zim::SuggestionSearcher>> SuggestionSearcherCache; typedef ConcurrentCache<string, std::shared_ptr<zim::SuggestionSearcher>> SuggestionSearcherCache;
class Entry; class Entry;