query: support negative mime and catg clauses: -mime:text/plain

This commit is contained in:
Jean-Francois Dockes 2011-05-15 09:29:24 +02:00
parent b9be9e58d5
commit ce9e9e4d00
4 changed files with 70 additions and 24 deletions

View File

@ -61,11 +61,14 @@ static Rcl::SearchData *wasaQueryToRcl(RclConfig *config, WasaQuery *wasa,
if (!stringicmp("mime", (*it)->m_fieldspec) ||
!stringicmp("format", (*it)->m_fieldspec)) {
if ((*it)->m_op != WasaQuery::OP_LEAF) {
reason = "Negative mime/format clauses not supported yet";
if ((*it)->m_op == WasaQuery::OP_LEAF) {
sdata->addFiletype((*it)->m_value);
} else if ((*it)->m_op == WasaQuery::OP_EXCL) {
sdata->remFiletype((*it)->m_value);
} else {
reason = "internal error: mime clause neither leaf not excl??";
return 0;
}
sdata->addFiletype((*it)->m_value);
continue;
}
@ -73,8 +76,10 @@ static Rcl::SearchData *wasaQueryToRcl(RclConfig *config, WasaQuery *wasa,
// categories like "audio", "presentation", etc.
if (!stringicmp("rclcat", (*it)->m_fieldspec) ||
!stringicmp("type", (*it)->m_fieldspec)) {
if ((*it)->m_op != WasaQuery::OP_LEAF) {
reason = "Negative rclcat/type clauses not supported yet";
if ((*it)->m_op != WasaQuery::OP_LEAF &&
(*it)->m_op != WasaQuery::OP_EXCL) {
reason = "internal error: rclcat/type clause neither leaf"
"nor excl??";
return 0;
}
list<string> mtypes;
@ -82,7 +87,10 @@ static Rcl::SearchData *wasaQueryToRcl(RclConfig *config, WasaQuery *wasa,
&& !mtypes.empty()) {
for (list<string>::iterator mit = mtypes.begin();
mit != mtypes.end(); mit++) {
sdata->addFiletype(*mit);
if ((*it)->m_op == WasaQuery::OP_LEAF)
sdata->addFiletype(*mit);
else
sdata->remFiletype(*mit);
}
} else {
reason = "Unknown rclcat/type value: no mime types found";

View File

@ -17,6 +17,7 @@
// Handle translation from rcl's SearchData structures to Xapian Queries
#include <stdio.h>
#include <fnmatch.h>
#include <string>
#include <vector>
@ -135,6 +136,35 @@ date_range_filter(int y1, int m1, int d1, int y2, int m2, int d2)
return Xapian::Query(Xapian::Query::OP_OR, v.begin(), v.end());
}
// Expand categories and mime type wild card exps
bool SearchData::expandFileTypes(RclConfig *cfg, vector<string>& tps)
{
if (!cfg) {
LOGFATAL(("Db::expandFileTypes: null configuration!!\n"));
return false;
}
vector<string> exptps;
list<string> alltypes = cfg->getAllMimeTypes();
for (vector<string>::iterator it = tps.begin(); it != tps.end(); it++) {
if (cfg->isMimeCategory(*it)) {
list<string>tps;
cfg->getMimeCatTypes(*it, tps);
exptps.insert(exptps.end(), tps.begin(), tps.end());
} else {
for (list<string>::const_iterator ait = alltypes.begin();
ait != alltypes.end(); ait++) {
if (fnmatch(it->c_str(), ait->c_str(), FNM_CASEFOLD)
!= FNM_NOMATCH) {
exptps.push_back(*ait);
}
}
}
}
tps = exptps;
return true;
}
bool SearchData::toNativeQuery(Rcl::Db &db, void *d)
{
Xapian::Query xq;
@ -220,24 +250,11 @@ bool SearchData::toNativeQuery(Rcl::Db &db, void *d)
// Add the file type filtering clause if any
if (!m_filetypes.empty()) {
vector<string> exptps;
exptps.reserve(m_filetypes.size());
// Expand categories
RclConfig *cfg = db.getConf();
for (vector<string>::iterator it = m_filetypes.begin();
it != m_filetypes.end(); it++) {
if (cfg && cfg->isMimeCategory(*it)) {
list<string>tps;
cfg->getMimeCatTypes(*it, tps);
exptps.insert(exptps.end(), tps.begin(), tps.end());
} else {
exptps.push_back(*it);
}
}
expandFileTypes(db.getConf(), m_filetypes);
Xapian::Query tq;
for (vector<string>::iterator it = exptps.begin();
it != exptps.end(); it++) {
for (vector<string>::iterator it = m_filetypes.begin();
it != m_filetypes.end(); it++) {
string term = "T" + *it;
LOGDEB0(("Adding file type term: [%s]\n", term.c_str()));
tq = tq.empty() ? Xapian::Query(term) :
@ -246,6 +263,21 @@ bool SearchData::toNativeQuery(Rcl::Db &db, void *d)
xq = xq.empty() ? tq : Xapian::Query(Xapian::Query::OP_FILTER, xq, tq);
}
// Add the neg file type filtering clause if any
if (!m_nfiletypes.empty()) {
expandFileTypes(db.getConf(), m_nfiletypes);
Xapian::Query tq;
for (vector<string>::iterator it = m_nfiletypes.begin();
it != m_nfiletypes.end(); it++) {
string term = "T" + *it;
LOGDEB0(("Adding negative file type term: [%s]\n", term.c_str()));
tq = tq.empty() ? Xapian::Query(term) :
Xapian::Query(Xapian::Query::OP_OR, tq, Xapian::Query(term));
}
xq = xq.empty() ? tq : Xapian::Query(Xapian::Query::OP_AND_NOT, xq, tq);
}
// Add the directory filtering clause
if (!m_topdir.empty()) {
vector<string> vpath;

View File

@ -31,6 +31,8 @@
#include "refcntr.h"
#include "smallut.h"
class RclConfig;
#ifndef NO_NAMESPACES
using std::vector;
using std::string;
@ -113,6 +115,8 @@ public:
/** Add file type for filtering results */
void addFiletype(const string& ft) {m_filetypes.push_back(ft);}
/** Add file type to not wanted list */
void remFiletype(const string& ft) {m_nfiletypes.push_back(ft);}
void setStemlang(const string& lang = "english") {m_stemlang = lang;}
@ -140,6 +144,7 @@ private:
SClType m_tp; // Only SCLT_AND or SCLT_OR here
vector<SearchDataClause*> m_query;
vector<string> m_filetypes; // Restrict to filetypes if set.
vector<string> m_nfiletypes; // Unwanted file types
string m_topdir; // Restrict to subtree.
bool m_topdirexcl; // Invert meaning
bool m_haveDates;
@ -150,6 +155,7 @@ private:
string m_reason;
bool m_haveWildCards;
string m_stemlang;
bool expandFileTypes(RclConfig *cfg, vector<string>& exptps);
/* Copyconst and assignment private and forbidden */
SearchData(const SearchData &) {}
SearchData& operator=(const SearchData&) {return *this;};

View File

@ -239,6 +239,7 @@ media = \
image/gif \
image/jpeg \
image/png \
image/svg+xml \
image/tiff \
video/mp2p \
video/mp2t \
@ -256,5 +257,4 @@ other = application/vnd.sun.xml.draw \
application/vnd.sun.xml.draw.template \
application/vnd.sun.xml.math \
application/x-fsdirectory \
application/zip \
image/svg+xml \
application/zip