mirror of https://github.com/kiwix/libkiwix.git
Catalog filtering by tags works via Xapian
This commit is contained in:
parent
19e195cb7d
commit
9c7366890d
|
@ -129,6 +129,9 @@ class Filter {
|
||||||
bool hasCreator() const;
|
bool hasCreator() const;
|
||||||
const std::string& getCreator() const { return _creator; }
|
const std::string& getCreator() const { return _creator; }
|
||||||
|
|
||||||
|
const Tags& getAcceptTags() const { return _acceptTags; }
|
||||||
|
const Tags& getRejectTags() const { return _rejectTags; }
|
||||||
|
|
||||||
private: // functions
|
private: // functions
|
||||||
friend class Library;
|
friend class Library;
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,7 @@ void Library::updateBookDB(const Book& book)
|
||||||
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());
|
const std::string creator = normalizeText(book.getCreator());
|
||||||
|
const std::string tags = book.getTags(); // normalization not needed
|
||||||
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);
|
||||||
|
@ -289,6 +290,7 @@ void Library::updateBookDB(const Book& book)
|
||||||
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.add_value(6, creator);
|
||||||
|
doc.add_value(7, tags);
|
||||||
doc.set_data(book.getId());
|
doc.set_data(book.getId());
|
||||||
|
|
||||||
indexer.index_text(title, 1, "S");
|
indexer.index_text(title, 1, "S");
|
||||||
|
@ -299,6 +301,9 @@ void Library::updateBookDB(const Book& book)
|
||||||
indexer.index_text(publisher, 1, "XP");
|
indexer.index_text(publisher, 1, "XP");
|
||||||
indexer.index_text(creator, 1, "A");
|
indexer.index_text(creator, 1, "A");
|
||||||
|
|
||||||
|
for ( const auto& tag : split(tags, ";") )
|
||||||
|
doc.add_boolean_term("XT" + tag);
|
||||||
|
|
||||||
// Index fields without prefixes for general search
|
// Index fields without prefixes for general search
|
||||||
indexer.index_text(title);
|
indexer.index_text(title);
|
||||||
indexer.increase_termpos();
|
indexer.increase_termpos();
|
||||||
|
@ -335,6 +340,7 @@ Xapian::Query buildXapianQueryFromFilterQuery(const Filter& filter)
|
||||||
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");
|
queryParser.add_prefix("creator", "A");
|
||||||
|
queryParser.add_prefix("tag", "XT");
|
||||||
const auto partialQueryFlag = filter.queryIsPartial()
|
const auto partialQueryFlag = filter.queryIsPartial()
|
||||||
? Xapian::QueryParser::FLAG_PARTIAL
|
? Xapian::QueryParser::FLAG_PARTIAL
|
||||||
: 0;
|
: 0;
|
||||||
|
@ -385,6 +391,21 @@ Xapian::Query creatorQuery(const std::string& creator)
|
||||||
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 tagsQuery(const Filter::Tags& acceptTags, const Filter::Tags& rejectTags)
|
||||||
|
{
|
||||||
|
Xapian::Query q = Xapian::Query(std::string());
|
||||||
|
if (!acceptTags.empty()) {
|
||||||
|
for ( const auto& tag : acceptTags )
|
||||||
|
q &= Xapian::Query("XT" + tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rejectTags.empty()) {
|
||||||
|
for ( const auto& tag : rejectTags )
|
||||||
|
q = Xapian::Query(Xapian::Query::OP_AND_NOT, q, "XT" + tag);
|
||||||
|
}
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
Xapian::Query buildXapianQuery(const Filter& filter)
|
Xapian::Query buildXapianQuery(const Filter& filter)
|
||||||
{
|
{
|
||||||
auto q = buildXapianQueryFromFilterQuery(filter);
|
auto q = buildXapianQueryFromFilterQuery(filter);
|
||||||
|
@ -403,6 +424,10 @@ Xapian::Query buildXapianQuery(const Filter& filter)
|
||||||
if ( filter.hasCreator() ) {
|
if ( filter.hasCreator() ) {
|
||||||
q = Xapian::Query(Xapian::Query::OP_AND, q, creatorQuery(filter.getCreator()));
|
q = Xapian::Query(Xapian::Query::OP_AND, q, creatorQuery(filter.getCreator()));
|
||||||
}
|
}
|
||||||
|
if ( !filter.getAcceptTags().empty() || !filter.getRejectTags().empty() ) {
|
||||||
|
const auto tq = tagsQuery(filter.getAcceptTags(), filter.getRejectTags());
|
||||||
|
q = Xapian::Query(Xapian::Query::OP_AND, q, tq);;
|
||||||
|
}
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,28 +761,6 @@ bool Filter::accept(const Book& book) const
|
||||||
|
|
||||||
FILTER(MAXSIZE, book.getSize() <= _maxSize)
|
FILTER(MAXSIZE, book.getSize() <= _maxSize)
|
||||||
|
|
||||||
if (ACTIVE(ACCEPTTAGS)) {
|
|
||||||
if (!_acceptTags.empty()) {
|
|
||||||
auto vBookTags = split(book.getTags(), ";");
|
|
||||||
std::set<std::string> sBookTags(vBookTags.begin(), vBookTags.end());
|
|
||||||
for (auto& t: _acceptTags) {
|
|
||||||
if (sBookTags.find(t) == sBookTags.end()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ACTIVE(REJECTTAGS)) {
|
|
||||||
if (!_rejectTags.empty()) {
|
|
||||||
auto vBookTags = split(book.getTags(), ";");
|
|
||||||
std::set<std::string> sBookTags(vBookTags.begin(), vBookTags.end());
|
|
||||||
for (auto& t: _rejectTags) {
|
|
||||||
if (sBookTags.find(t) != sBookTags.end()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue