Catalog filtering by creator works via Xapian

This commit is contained in:
Veloman Yunkan 2021-04-13 00:51:53 +04:00
parent d3d5abe14d
commit 3d5fd8f585
3 changed files with 54 additions and 6 deletions

View File

@ -123,6 +123,9 @@ class Filter {
bool hasPublisher() const; bool hasPublisher() const;
const std::string& getPublisher() const { return _publisher; } const std::string& getPublisher() const { return _publisher; }
bool hasCreator() const;
const std::string& getCreator() const { return _creator; }
private: private:
friend class Library; friend class Library;

View File

@ -281,12 +281,14 @@ void Library::updateBookDB(const Book& book)
const std::string name = book.getName(); // this is supposed to be normalized const std::string name = book.getName(); // this is supposed to be normalized
const std::string category = book.getCategory(); // this is supposed to be normalized const std::string category = book.getCategory(); // this is supposed to be normalized
const std::string publisher = normalizeText(book.getPublisher()); const std::string publisher = normalizeText(book.getPublisher());
const std::string creator = normalizeText(book.getCreator());
doc.add_value(0, title); doc.add_value(0, title);
doc.add_value(1, desc); doc.add_value(1, desc);
doc.add_value(2, name); doc.add_value(2, name);
doc.add_value(3, category); doc.add_value(3, category);
doc.add_value(4, lang); doc.add_value(4, lang);
doc.add_value(5, publisher); doc.add_value(5, publisher);
doc.add_value(6, creator);
doc.set_data(book.getId()); doc.set_data(book.getId());
indexer.index_text(title, 1, "S"); indexer.index_text(title, 1, "S");
@ -295,6 +297,7 @@ void Library::updateBookDB(const Book& book)
indexer.index_text(category, 1, "XC"); indexer.index_text(category, 1, "XC");
indexer.index_text(lang, 1, "L"); indexer.index_text(lang, 1, "L");
indexer.index_text(publisher, 1, "XP"); indexer.index_text(publisher, 1, "XP");
indexer.index_text(creator, 1, "A");
// Index fields without prefixes for general search // Index fields without prefixes for general search
indexer.index_text(title); indexer.index_text(title);
@ -331,6 +334,7 @@ Xapian::Query buildXapianQueryFromFilterQuery(const Filter& filter)
queryParser.add_prefix("category", "XC"); queryParser.add_prefix("category", "XC");
queryParser.add_prefix("lang", "L"); queryParser.add_prefix("lang", "L");
queryParser.add_prefix("publisher", "XP"); queryParser.add_prefix("publisher", "XP");
queryParser.add_prefix("creator", "A");
const auto partialQueryFlag = filter.queryIsPartial() const auto partialQueryFlag = filter.queryIsPartial()
? Xapian::QueryParser::FLAG_PARTIAL ? Xapian::QueryParser::FLAG_PARTIAL
: 0; : 0;
@ -371,6 +375,16 @@ Xapian::Query publisherQuery(const std::string& publisher)
return Xapian::Query(Xapian::Query::OP_PHRASE, q.get_terms_begin(), q.get_terms_end(), q.get_length()); return Xapian::Query(Xapian::Query::OP_PHRASE, q.get_terms_begin(), q.get_terms_end(), q.get_length());
} }
Xapian::Query creatorQuery(const std::string& creator)
{
Xapian::QueryParser queryParser;
queryParser.set_default_op(Xapian::Query::OP_OR);
queryParser.set_stemming_strategy(Xapian::QueryParser::STEM_NONE);
const auto flags = 0;
const auto q = queryParser.parse_query(normalizeText(creator), flags, "A");
return Xapian::Query(Xapian::Query::OP_PHRASE, q.get_terms_begin(), q.get_terms_end(), q.get_length());
}
Xapian::Query buildXapianQuery(const Filter& filter) Xapian::Query buildXapianQuery(const Filter& filter)
{ {
auto q = buildXapianQueryFromFilterQuery(filter); auto q = buildXapianQueryFromFilterQuery(filter);
@ -386,6 +400,9 @@ Xapian::Query buildXapianQuery(const Filter& filter)
if ( filter.hasPublisher() ) { if ( filter.hasPublisher() ) {
q = Xapian::Query(Xapian::Query::OP_AND, q, publisherQuery(filter.getPublisher())); q = Xapian::Query(Xapian::Query::OP_AND, q, publisherQuery(filter.getPublisher()));
} }
if ( filter.hasCreator() ) {
q = Xapian::Query(Xapian::Query::OP_AND, q, creatorQuery(filter.getCreator()));
}
return q; return q;
} }
@ -698,6 +715,11 @@ bool Filter::hasPublisher() const
return ACTIVE(_PUBLISHER); return ACTIVE(_PUBLISHER);
} }
bool Filter::hasCreator() const
{
return ACTIVE(_CREATOR);
}
bool Filter::accept(const Book& book) const bool Filter::accept(const Book& book) const
{ {
auto local = !book.getPath().empty(); auto local = !book.getPath().empty();
@ -713,7 +735,6 @@ bool Filter::accept(const Book& book) const
FILTER(_NOREMOTE, !remote) FILTER(_NOREMOTE, !remote)
FILTER(MAXSIZE, book.getSize() <= _maxSize) FILTER(MAXSIZE, book.getSize() <= _maxSize)
FILTER(_CREATOR, book.getCreator() == _creator)
if (ACTIVE(ACCEPTTAGS)) { if (ACTIVE(ACCEPTTAGS)) {
if (!_acceptTags.empty()) { if (!_acceptTags.empty()) {

View File

@ -472,18 +472,42 @@ TEST_F(LibraryTest, filterByCreator)
"Granblue Fantasy Wiki" "Granblue Fantasy Wiki"
); );
// filtering by creator is case sensitive // filtering by creator is case and diacritics insensitive
EXPECT_FILTER_RESULTS(kiwix::Filter().creator("wiki"), EXPECT_FILTER_RESULTS(kiwix::Filter().creator("wIkï"),
/* no results */ "Granblue Fantasy Wiki"
); );
// filtering by creator requires full match of the full author/creator name // filtering by creator doesn't requires full match of the full creator name
EXPECT_FILTER_RESULTS(kiwix::Filter().creator("Stack"), EXPECT_FILTER_RESULTS(kiwix::Filter().creator("Stack"),
/* no results */ "Islam Stack Exchange",
"Movies & TV Stack Exchange",
"Mythology & Folklore Stack Exchange"
); );
// filtering by creator requires a full phrase match (ignoring some non-word terms)
EXPECT_FILTER_RESULTS(kiwix::Filter().creator("Movies & TV Stack Exchange"), EXPECT_FILTER_RESULTS(kiwix::Filter().creator("Movies & TV Stack Exchange"),
"Movies & TV Stack Exchange" "Movies & TV Stack Exchange"
); );
EXPECT_FILTER_RESULTS(kiwix::Filter().creator("Movies & TV"),
"Movies & TV Stack Exchange"
);
EXPECT_FILTER_RESULTS(kiwix::Filter().creator("Movies TV"),
"Movies & TV Stack Exchange"
);
EXPECT_FILTER_RESULTS(kiwix::Filter().creator("TV & Movies"),
/* no results */
);
EXPECT_FILTER_RESULTS(kiwix::Filter().creator("TV Movies"),
/* no results */
);
EXPECT_FILTER_RESULTS(kiwix::Filter().query("creator:Wikipedia"),
"Encyclopédie de la Tunisie",
"Géographie par Wikipédia",
"Mathématiques",
"Ray Charles"
);
} }
TEST_F(LibraryTest, filterByPublisher) TEST_F(LibraryTest, filterByPublisher)