--- a/src/rcldb/searchdata.cpp
+++ b/src/rcldb/searchdata.cpp
@@ -1,5 +1,5 @@
#ifndef lint
-static char rcsid[] = "@(#$Id: searchdata.cpp,v 1.7 2006-12-19 12:11:21 dockes Exp $ (C) 2006 J.F.Dockes";
+static char rcsid[] = "@(#$Id: searchdata.cpp,v 1.8 2007-01-17 13:53:41 dockes Exp $ (C) 2006 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@@ -154,6 +154,7 @@
bool translate(const string &iq,
+ const string &prefix,
string &ermsg,
list<Xapian::Query> &pqueries,
int slack = 0, bool useNear = false);
@@ -255,6 +256,14 @@
// vector)
comb.pop_back();
}
+}
+
+static void addPrefix(list<string>& terms, const string& prefix)
+{
+ if (prefix.empty())
+ return;
+ for (list<string>::iterator it = terms.begin(); it != terms.end(); it++)
+ it->insert(0, prefix);
}
/**
@@ -271,6 +280,7 @@
* count)
*/
bool StringToXapianQ::translate(const string &iq,
+ const string &prefix,
string &ermsg,
list<Xapian::Query> &pqueries,
int slack, bool useNear)
@@ -301,24 +311,25 @@
splitterS.text_to_words(*it);
TextSplit splitterW(&splitDataW, TextSplit::TXTS_NOSPANS);
splitterW.text_to_words(*it);
- wsQData& splitData = splitDataS;
- if (splitDataS.terms.size() > 1 && splitDataS.terms.size() !=
- splitDataW.terms.size())
- splitData = splitDataW;
+ wsQData *splitData = &splitDataS;
+ if (splitDataS.terms.size() > 1 &&
+ splitDataS.terms.size() != splitDataW.terms.size())
+ splitData = &splitDataW;
LOGDEB1(("strToXapianQ: splitter term count: %d\n",
- splitData.terms.size()));
- switch(splitData.terms.size()) {
+ splitData->terms.size()));
+ switch(splitData->terms.size()) {
case 0: continue;// ??
case 1: // Not a real phrase: one term
{
- string term = splitData.terms.front();
+ string term = splitData->terms.front();
list<string> exp;
maybeStemExp(false, term, exp);
+ m_terms.insert(m_terms.end(), exp.begin(), exp.end());
// Push either term or OR of stem-expanded set
+ addPrefix(exp, prefix);
pqueries.push_back(Xapian::Query(Xapian::Query::OP_OR,
exp.begin(), exp.end()));
- m_terms.insert(m_terms.end(), exp.begin(), exp.end());
}
break;
@@ -329,8 +340,8 @@
list<Xapian::Query> orqueries;
bool hadmultiple = false;
vector<vector<string> >groups;
- for (vector<string>::iterator it = splitData.terms.begin();
- it != splitData.terms.end(); it++) {
+ for (vector<string>::iterator it = splitData->terms.begin();
+ it != splitData->terms.end(); it++) {
// Some version of xapian will accept only one OR clause
// inside NEAR, all others must be leafs
bool nostemexp =
@@ -341,6 +352,7 @@
maybeStemExp(nostemexp, *it, exp);
groups.push_back(vector<string>(exp.begin(), exp.end()));
+ addPrefix(exp, prefix);
orqueries.push_back(Xapian::Query(Xapian::Query::OP_OR,
exp.begin(), exp.end()));
#ifdef XAPIAN_NEAR_EXPAND_SINGLE_BUF
@@ -352,7 +364,7 @@
pqueries.push_back(Xapian::Query(op,
orqueries.begin(),
orqueries.end(),
- splitData.terms.size() + slack));
+ splitData->terms.size() + slack));
// Add NEAR/PHRASE groups to the highlighting data. Must
// push all combinations
vector<vector<string> > allcombs;
@@ -376,6 +388,28 @@
return false;
}
return true;
+}
+
+// Try to translate field specification into field prefix. This should
+// probably be an Rcl::Db method and much more configurable (store
+// prefix translation list in config ?)
+static string fieldToPrefix(const string& i_field)
+{
+ static map<string, string> fldToPrefs;
+ if (fldToPrefs.empty()) {
+ fldToPrefs["title"] = "S";
+ fldToPrefs["caption"] = "S";
+ fldToPrefs["subject"] = "S";
+ fldToPrefs["author"] = "A";
+ fldToPrefs["from"] = "A";
+ fldToPrefs["keyword"] = "K";
+ }
+ string fld(i_field);
+ stringtolower(fld);
+ map<string, string>::const_iterator it = fldToPrefs.find(fld);
+ if (it != fldToPrefs.end())
+ return it->second;
+ return "";
}
// Translate a simple OR, AND, or EXCL search clause.
@@ -397,9 +431,12 @@
LOGERR(("SearchDataClauseSimple: bad m_tp %d\n", m_tp));
return false;
}
+ string prefix;
+ if (!m_field.empty())
+ prefix = fieldToPrefix(m_field);
list<Xapian::Query> pqueries;
StringToXapianQ tr(db, stemlang);
- if (!tr.translate(m_text, m_reason, pqueries))
+ if (!tr.translate(m_text, prefix, m_reason, pqueries))
return false;
if (pqueries.empty()) {
LOGERR(("SearchDataClauseSimple: resolved to null query\n"));
@@ -436,13 +473,17 @@
list<Xapian::Query> pqueries;
Xapian::Query nq;
+
+ string prefix;
+ if (!m_field.empty())
+ prefix = fieldToPrefix(m_field);
// Use stringToXapianQueries to lowercase and simplify the phrase
// terms etc. The result should be a single element list
string s = string("\"") + m_text + string("\"");
bool useNear = m_tp == SCLT_NEAR;
StringToXapianQ tr(db, stemlang);
- if (!tr.translate(s, m_reason, pqueries, m_slack, useNear))
+ if (!tr.translate(s, prefix, m_reason, pqueries, m_slack, useNear))
return false;
if (pqueries.empty()) {
LOGERR(("SearchDataClauseDist: resolved to null query\n"));