Gui search: make autophrase work with a query language query

This commit is contained in:
Jean-Francois Dockes 2010-12-21 16:00:25 +01:00
parent 7d06dcd5a9
commit 107e02b74a
3 changed files with 82 additions and 3 deletions

View File

@ -139,6 +139,9 @@ void SSearch::startSimpleSearch()
QString::fromAscii(reason.c_str()));
return;
}
if (prefs.ssearchAutoPhrase) {
sdata->maybeAddAutoPhrase();
}
} else {
sdata = new Rcl::SearchData(Rcl::SCLT_OR);
if (sdata == 0) {

View File

@ -242,7 +242,7 @@ bool SearchData::toNativeQuery(Rcl::Db &db, void *d)
for (vector<string>::iterator it = exptps.begin();
it != exptps.end(); it++) {
string term = "T" + *it;
LOGDEB(("Adding file type term: [%s]\n", term.c_str()));
LOGDEB0(("Adding file type term: [%s]\n", term.c_str()));
tq = tq.empty() ? Xapian::Query(term) :
Xapian::Query(Xapian::Query::OP_OR, tq, Xapian::Query(term));
}
@ -268,6 +268,70 @@ bool SearchData::toNativeQuery(Rcl::Db &db, void *d)
return true;
}
bool SearchData::maybeAddAutoPhrase()
{
LOGDEB0(("SearchData::maybeAddAutoPhrase()\n"));
if (!m_query.size()) {
LOGDEB2(("SearchData::maybeAddAutoPhrase: empty query\n"));
return false;
}
string field;
string words;
// Walk the clause list. If we find any non simple clause or different
// field names, bail out.
for (qlist_it_t it = m_query.begin(); it != m_query.end(); it++) {
SClType tp = (*it)->m_tp;
if (tp != SCLT_AND && tp != SCLT_OR) {
LOGDEB2(("SearchData::maybeAddAutoPhrase: complex clause\n"));
return false;
}
SearchDataClauseSimple *clp =
dynamic_cast<SearchDataClauseSimple*>(*it);
if (clp == 0) {
LOGDEB2(("SearchData::maybeAddAutoPhrase: dyncast failed\n"));
return false;
}
if (it == m_query.begin()) {
field = clp->getfield();
} else {
if (clp->getfield().compare(field)) {
LOGDEB2(("SearchData::maybeAddAutoPhrase: different fields\n"));
return false;
}
}
if (!words.empty())
words += " ";
words += clp->gettext();
}
if (words.find_first_of("\"*[]?") != string::npos && // has wildcards
TextSplit::countWords(words) <= 1) { // Just one word.
LOGDEB2(("SearchData::maybeAddAutoPhrase: wildcards or single word\n"));
return false;
}
SearchDataClauseDist *nclp =
new SearchDataClauseDist(SCLT_PHRASE, words, 0, field);
if (m_tp == SCLT_OR) {
addClause(nclp);
} else {
// My type is AND. Change it to OR and insert two queries, one
// being the original query as a subquery, the other the
// phrase.
SearchData *sd = new SearchData(m_tp);
sd->m_query = m_query;
m_tp = SCLT_OR;
m_query.clear();
SearchDataClauseSub *oq =
new SearchDataClauseSub(SCLT_OR, RefCntr<SearchData>(sd));
addClause(oq);
addClause(nclp);
}
return true;
}
// Add clause to current list. OR lists cant have EXCL clauses.
bool SearchData::addClause(SearchDataClause* cl)
{
@ -284,7 +348,7 @@ bool SearchData::addClause(SearchDataClause* cl)
// Make me all new
void SearchData::erase() {
LOGDEB(("SearchData::erase\n"));
LOGDEB0(("SearchData::erase\n"));
m_tp = SCLT_AND;
for (qlist_it_t it = m_query.begin(); it != m_query.end(); it++)
delete *it;

View File

@ -73,7 +73,10 @@ class SearchData {
public:
SearchData(SClType tp)
: m_tp(tp), m_haveDates(false), m_haveWildCards(false)
{}
{
if (m_tp != SCLT_OR && m_tp != SCLT_AND)
m_tp = SCLT_OR;
}
~SearchData() {erase();}
/** Make pristine */
@ -91,6 +94,13 @@ public:
/** We become the owner of cl and will delete it */
bool addClause(SearchDataClause *cl);
/** If this is a simple query (one field only, no distance clauses),
add phrase made of query terms to query, so that docs containing the
user terms in order will have higher relevance. This must be called
before toNativeQuery().
*/
bool maybeAddAutoPhrase();
/** Set/get top subdirectory for filtering results */
void setTopdir(const string& t) {m_topdir = t;}
string getTopdir() {return m_topdir;}
@ -207,6 +217,8 @@ public:
{
terms.insert(terms.end(), m_uterms.begin(), m_uterms.end());
}
virtual const string& gettext() {return m_text;}
virtual const string& getfield() {return m_field;}
protected:
string m_text; // Raw user entry text.
string m_field; // Field specification if any