ensure that recoll configured with indexStripChars=1 runs as compiled with -DRCL_INDEX_STRIPCHARS
--HG-- branch : CASEDIACSENS
This commit is contained in:
+21
-14
@@ -63,17 +63,19 @@ bool createExpansionDbs(Xapian::WritableDatabase& wdb,
|
||||
// Unaccented stem dbs
|
||||
vector<XapWritableComputableSynFamMember> unacstemdbs;
|
||||
// We can reuse the same stemmer pointers, the objects are stateless.
|
||||
for (unsigned int i = 0; i < langs.size(); i++) {
|
||||
unacstemdbs.push_back(
|
||||
XapWritableComputableSynFamMember(wdb, synFamStemUnac, langs[i],
|
||||
stemmers.back().getptr()));
|
||||
unacstemdbs.back().recreate();
|
||||
if (!o_index_stripchars) {
|
||||
for (unsigned int i = 0; i < langs.size(); i++) {
|
||||
unacstemdbs.push_back(
|
||||
XapWritableComputableSynFamMember(wdb, synFamStemUnac, langs[i],
|
||||
stemmers.back().getptr()));
|
||||
unacstemdbs.back().recreate();
|
||||
}
|
||||
}
|
||||
|
||||
SynTermTransUnac transunac(UNACOP_UNACFOLD);
|
||||
XapWritableComputableSynFamMember
|
||||
diacasedb(wdb, synFamDiCa, "all", &transunac);
|
||||
diacasedb.recreate();
|
||||
if (!o_index_stripchars)
|
||||
diacasedb.recreate();
|
||||
#endif
|
||||
|
||||
// Walk the list of all terms, and stem/unac each.
|
||||
@@ -109,8 +111,10 @@ bool createExpansionDbs(Xapian::WritableDatabase& wdb,
|
||||
// is the input to the stem db, and add a synonym from the
|
||||
// stripped term to the cased and accented one, for accent
|
||||
// and case expansion at query time
|
||||
unacmaybefold(*it, lower, "UTF-8", UNACOP_FOLD);
|
||||
diacasedb.addSynonym(*it);
|
||||
if (!o_index_stripchars) {
|
||||
unacmaybefold(*it, lower, "UTF-8", UNACOP_FOLD);
|
||||
diacasedb.addSynonym(*it);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create stemming synonym for every language. The input is the
|
||||
@@ -124,12 +128,15 @@ bool createExpansionDbs(Xapian::WritableDatabase& wdb,
|
||||
// the unaccented term. While this may be incorrect, it is
|
||||
// also necessary for searching in a diacritic-unsensitive
|
||||
// way on a raw index
|
||||
string unac;
|
||||
unacmaybefold(lower, unac, "UTF-8", UNACOP_UNAC);
|
||||
if (unac != lower)
|
||||
for (unsigned int i = 0; i < langs.size(); i++) {
|
||||
unacstemdbs[i].addSynonym(unac);
|
||||
if (!o_index_stripchars) {
|
||||
string unac;
|
||||
unacmaybefold(lower, unac, "UTF-8", UNACOP_UNAC);
|
||||
if (unac != lower) {
|
||||
for (unsigned int i = 0; i < langs.size(); i++) {
|
||||
unacstemdbs[i].addSynonym(unac);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} XCATCHERROR(ermsg);
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
|
||||
namespace Rcl {
|
||||
|
||||
/* A Capitals/Diacritics removal functor for using with
|
||||
XapComputableSynFamMember */
|
||||
/** A Capitals/Diacritics removal functor for using with
|
||||
* XapComputableSynFamMember */
|
||||
class SynTermTransUnac : public SynTermTrans {
|
||||
public:
|
||||
/** Constructor
|
||||
* @param op defines if we remove diacritics, case or both
|
||||
*/
|
||||
SynTermTransUnac(UnacOp op)
|
||||
: m_op(op)
|
||||
{
|
||||
@@ -43,7 +46,9 @@ public:
|
||||
UnacOp m_op;
|
||||
};
|
||||
|
||||
/** Walk the Xapian term list and create all the expansion dbs in one go */
|
||||
/** Walk the Xapian term list and create all the expansion dbs in one go.
|
||||
*
|
||||
*/
|
||||
extern bool createExpansionDbs(Xapian::WritableDatabase& wdb,
|
||||
const std::vector<std::string>& langs);
|
||||
}
|
||||
|
||||
+41
-17
@@ -92,10 +92,11 @@ const string start_of_field_term = "XXST";
|
||||
const string end_of_field_term = "XXND";
|
||||
static const string page_break_term = "XXPG";
|
||||
#else
|
||||
const string start_of_field_term = "XXST/";
|
||||
const string end_of_field_term = "XXND/";
|
||||
static const string page_break_term = "XXPG/";
|
||||
string start_of_field_term;
|
||||
string end_of_field_term;
|
||||
const string page_break_term = "XXPG/";
|
||||
#endif
|
||||
|
||||
// Field name for the unsplit file name. Has to exist in the field file
|
||||
// because of usage in termmatch()
|
||||
static const string unsplitFilenameFieldName = "rclUnsplitFN";
|
||||
@@ -683,6 +684,18 @@ Db::Db(RclConfig *cfp)
|
||||
m_curtxtsz(0), m_flushtxtsz(0), m_occtxtsz(0), m_occFirstCheck(1),
|
||||
m_maxFsOccupPc(0), m_mode(Db::DbRO)
|
||||
{
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
if (start_of_field_term.empty()) {
|
||||
if (o_index_stripchars) {
|
||||
start_of_field_term = "XXST";
|
||||
end_of_field_term = "XXND";
|
||||
} else {
|
||||
start_of_field_term = "XXST/";
|
||||
end_of_field_term = "XXND/";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_ndb = new Native(this);
|
||||
if (m_config) {
|
||||
m_config->getConfParam("maxfsoccuppc", &m_maxFsOccupPc);
|
||||
@@ -886,12 +899,13 @@ int Db::termDocCnt(const string& _term)
|
||||
return -1;
|
||||
|
||||
string term = _term;
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
if (!unacmaybefold(_term, term, "UTF-8", UNACOP_UNACFOLD)) {
|
||||
LOGINFO(("Db::termDocCnt: unac failed for [%s]\n", _term.c_str()));
|
||||
return 0;
|
||||
}
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
if (o_index_stripchars)
|
||||
#endif
|
||||
if (!unacmaybefold(_term, term, "UTF-8", UNACOP_UNACFOLD)) {
|
||||
LOGINFO(("Db::termDocCnt: unac failed for [%s]\n", _term.c_str()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m_stops.isStop(term)) {
|
||||
LOGDEB1(("Db::termDocCnt [%s] in stop list\n", term.c_str()));
|
||||
@@ -1151,13 +1165,17 @@ string Db::getSpellingSuggestion(const string& word)
|
||||
{
|
||||
if (m_ndb == 0)
|
||||
return string();
|
||||
|
||||
string term = word;
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
if (o_index_stripchars)
|
||||
#endif
|
||||
if (!unacmaybefold(word, term, "UTF-8", UNACOP_UNACFOLD)) {
|
||||
LOGINFO(("Db::getSpelling: unac failed for [%s]\n", word.c_str()));
|
||||
return string();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!isSpellingCandidate(term))
|
||||
return string();
|
||||
return m_ndb->xrdb.get_spelling_suggestion(term);
|
||||
@@ -1266,9 +1284,12 @@ bool Db::addOrUpdate(const string &udi, const string &parent_udi,
|
||||
TermProc *nxt = &tpidx;
|
||||
TermProcStop tpstop(nxt, m_stops);nxt = &tpstop;
|
||||
//TermProcCommongrams tpcommon(nxt, m_stops); nxt = &tpcommon;
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
TermProcPrep tpprep(nxt); nxt = &tpprep;
|
||||
|
||||
TermProcPrep tpprep(nxt);
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
if (o_index_stripchars)
|
||||
#endif
|
||||
nxt = &tpprep;
|
||||
|
||||
TextSplitDb splitter(newdocument, nxt);
|
||||
tpidx.setTSD(&splitter);
|
||||
@@ -1951,12 +1972,15 @@ bool Db::termMatch(MatchType typ, const string &lang,
|
||||
// Get rid of capitals and accents
|
||||
|
||||
string droot = root;
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
if (!unacmaybefold(root, droot, "UTF-8", UNACOP_UNACFOLD)) {
|
||||
LOGERR(("Db::termMatch: unac failed for [%s]\n", root.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
if (o_index_stripchars)
|
||||
#endif
|
||||
if (!unacmaybefold(root, droot, "UTF-8", UNACOP_UNACFOLD)) {
|
||||
LOGERR(("Db::termMatch: unac failed for [%s]\n", root.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
string nochars = typ == ET_WILD ? cstr_wildSpecChars : cstr_regSpecChars;
|
||||
|
||||
string prefix;
|
||||
|
||||
+22
-9
@@ -129,18 +129,27 @@ extern void *DbUpdWorker(void*);
|
||||
|
||||
inline bool has_prefix(const string& trm)
|
||||
{
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
return !trm.empty() && 'A' <= trm[0] && trm[0] <= 'Z';
|
||||
#else
|
||||
return !trm.empty() && trm[0] == ':';
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
if (o_index_stripchars) {
|
||||
#endif
|
||||
return !trm.empty() && 'A' <= trm[0] && trm[0] <= 'Z';
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
} else {
|
||||
return !trm.empty() && trm[0] == ':';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline string wrap_prefix(const string& pfx)
|
||||
{
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
return pfx;
|
||||
#else
|
||||
return cstr_colon + pfx + cstr_colon;
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
if (o_index_stripchars) {
|
||||
#endif
|
||||
return pfx;
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
} else {
|
||||
return cstr_colon + pfx + cstr_colon;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -384,9 +393,13 @@ private:
|
||||
string version_string();
|
||||
|
||||
extern const string pathelt_prefix;
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
extern const string start_of_field_term;
|
||||
extern const string end_of_field_term;
|
||||
|
||||
#else
|
||||
extern string start_of_field_term;
|
||||
extern string end_of_field_term;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _DB_H_INCLUDED_ */
|
||||
|
||||
+173
-143
@@ -79,10 +79,22 @@ static const int original_term_wqf_booster = 10;
|
||||
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
#define bufprefix(BUF, L) {(BUF)[0] = L;}
|
||||
#define bpoffs 1
|
||||
#define bpoffs() 1
|
||||
#else
|
||||
#define bufprefix(BUF, L) {(BUF)[0] = ':'; (BUF)[1] = L; (BUF)[2] = ':';}
|
||||
#define bpoffs 3
|
||||
static inline void bufprefix(char *buf, char c)
|
||||
{
|
||||
if (o_index_stripchars) {
|
||||
buf[0] = c;
|
||||
} else {
|
||||
buf[0] = ':';
|
||||
buf[1] = c;
|
||||
buf[2] = ':';
|
||||
}
|
||||
}
|
||||
static inline int bpoffs()
|
||||
{
|
||||
return o_index_stripchars ? 1 : 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
static Xapian::Query
|
||||
@@ -92,7 +104,7 @@ date_range_filter(int y1, int m1, int d1, int y2, int m2, int d2)
|
||||
// only doing %d's !
|
||||
char buf[200];
|
||||
bufprefix(buf, 'D');
|
||||
sprintf(buf+bpoffs, "%04d%02d", y1, m1);
|
||||
sprintf(buf+bpoffs(), "%04d%02d", y1, m1);
|
||||
vector<Xapian::Query> v;
|
||||
|
||||
int d_last = monthdays(m1, y1);
|
||||
@@ -103,7 +115,7 @@ date_range_filter(int y1, int m1, int d1, int y2, int m2, int d2)
|
||||
// Deal with any initial partial month
|
||||
if (d1 > 1 || d_end < d_last) {
|
||||
for ( ; d1 <= d_end ; d1++) {
|
||||
sprintf(buf + 6 + bpoffs, "%02d", d1);
|
||||
sprintf(buf + 6 + bpoffs(), "%02d", d1);
|
||||
v.push_back(Xapian::Query(buf));
|
||||
}
|
||||
} else {
|
||||
@@ -117,32 +129,32 @@ date_range_filter(int y1, int m1, int d1, int y2, int m2, int d2)
|
||||
|
||||
int m_last = (y1 < y2) ? 12 : m2 - 1;
|
||||
while (++m1 <= m_last) {
|
||||
sprintf(buf + 4 + bpoffs, "%02d", m1);
|
||||
sprintf(buf + 4 + bpoffs(), "%02d", m1);
|
||||
bufprefix(buf, 'M');
|
||||
v.push_back(Xapian::Query(buf));
|
||||
}
|
||||
|
||||
if (y1 < y2) {
|
||||
while (++y1 < y2) {
|
||||
sprintf(buf + bpoffs, "%04d", y1);
|
||||
sprintf(buf + bpoffs(), "%04d", y1);
|
||||
bufprefix(buf, 'Y');
|
||||
v.push_back(Xapian::Query(buf));
|
||||
}
|
||||
sprintf(buf + bpoffs, "%04d", y2);
|
||||
sprintf(buf + bpoffs(), "%04d", y2);
|
||||
bufprefix(buf, 'M');
|
||||
for (m1 = 1; m1 < m2; m1++) {
|
||||
sprintf(buf + 4 + bpoffs, "%02d", m1);
|
||||
sprintf(buf + 4 + bpoffs(), "%02d", m1);
|
||||
v.push_back(Xapian::Query(buf));
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(buf + 2 + bpoffs, "%02d", m2);
|
||||
sprintf(buf + 2 + bpoffs(), "%02d", m2);
|
||||
|
||||
// Deal with any final partial month
|
||||
if (d2 < monthdays(m2, y2)) {
|
||||
bufprefix(buf, 'D');
|
||||
for (d1 = 1 ; d1 <= d2; d1++) {
|
||||
sprintf(buf + 6 + bpoffs, "%02d", d1);
|
||||
sprintf(buf + 6 + bpoffs(), "%02d", d1);
|
||||
v.push_back(Xapian::Query(buf));
|
||||
}
|
||||
} else {
|
||||
@@ -663,13 +675,13 @@ static void listVector(const string& what, const vector<string>&l)
|
||||
*/
|
||||
void StringToXapianQ::expandTerm(int mods,
|
||||
const string& term,
|
||||
vector<string>& exp, string &sterm,
|
||||
vector<string>& oexp, string &sterm,
|
||||
const string& prefix)
|
||||
{
|
||||
LOGDEB0(("expandTerm: mods 0x%x fld [%s] trm [%s] lang [%s]\n",
|
||||
mods, m_field.c_str(), term.c_str(), m_stemlang.c_str()));
|
||||
sterm.clear();
|
||||
exp.clear();
|
||||
oexp.clear();
|
||||
if (term.empty())
|
||||
return;
|
||||
|
||||
@@ -693,145 +705,161 @@ void StringToXapianQ::expandTerm(int mods,
|
||||
bool diac_sensitive = (mods & SearchDataClause::SDCM_DIACSENS) != 0;
|
||||
bool case_sensitive = (mods & SearchDataClause::SDCM_CASESENS) != 0;
|
||||
|
||||
// If we are working with a raw index, apply the rules for case and
|
||||
// diacritics sensitivity.
|
||||
if (o_index_stripchars) {
|
||||
diac_sensitive = case_sensitive = false;
|
||||
} else {
|
||||
// If we are working with a raw index, apply the rules for case and
|
||||
// diacritics sensitivity.
|
||||
|
||||
// If any character has a diacritic, we become
|
||||
// diacritic-sensitive. Note that the way that the test is
|
||||
// performed (conversion+comparison) will automatically ignore
|
||||
// accented characters which are actually a separate letter
|
||||
if (unachasaccents(term))
|
||||
diac_sensitive = true;
|
||||
// If any character has a diacritic, we become
|
||||
// diacritic-sensitive. Note that the way that the test is
|
||||
// performed (conversion+comparison) will automatically ignore
|
||||
// accented characters which are actually a separate letter
|
||||
if (unachasaccents(term))
|
||||
diac_sensitive = true;
|
||||
|
||||
// If any character apart the first is uppercase, we become case-sensitive.
|
||||
// The first character is reserved for turning off stemming. You need to
|
||||
// use a query language modifier to search for Floor in a case-sensitive
|
||||
// way.
|
||||
Utf8Iter it(term);
|
||||
it++;
|
||||
if (unachasuppercase(term.substr(it.getBpos())))
|
||||
case_sensitive = true;
|
||||
// If any character apart the first is uppercase, we become
|
||||
// case-sensitive. The first character is reserved for
|
||||
// turning off stemming. You need to use a query language
|
||||
// modifier to search for Floor in a case-sensitive way.
|
||||
Utf8Iter it(term);
|
||||
it++;
|
||||
if (unachasuppercase(term.substr(it.getBpos())))
|
||||
case_sensitive = true;
|
||||
|
||||
// If we are sensitive to case or diacritics turn stemming off
|
||||
if (diac_sensitive || case_sensitive)
|
||||
nostemexp = true;
|
||||
// If we are sensitive to case or diacritics turn stemming off
|
||||
if (diac_sensitive || case_sensitive)
|
||||
nostemexp = true;
|
||||
|
||||
if (!case_sensitive || !diac_sensitive)
|
||||
noexpansion = false;
|
||||
if (!case_sensitive || !diac_sensitive)
|
||||
noexpansion = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (noexpansion) {
|
||||
sterm = term;
|
||||
exp.push_back(prefix + term);
|
||||
} else {
|
||||
TermMatchResult res;
|
||||
if (haswild) {
|
||||
// Note that if there are wildcards, we do a direct from-index
|
||||
// expansion, which means that we are casediac-sensitive. There
|
||||
// would be nothing to prevent us to expand from the casediac
|
||||
// synonyms first. To be done later
|
||||
m_db.termMatch(Rcl::Db::ET_WILD, m_stemlang, term, res, -1,
|
||||
m_field);
|
||||
} else {
|
||||
sterm = term;
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
m_db.termMatch(Rcl::Db::ET_STEM, m_stemlang, term, res, -1,
|
||||
m_field);
|
||||
#else
|
||||
// No stem expansion when diacritic or case sensitivity is
|
||||
// set, it makes no sense (it would mess with the
|
||||
// diacritics anyway if they are not in the stem part).
|
||||
// In these 3 cases, perform appropriate expansion from
|
||||
// the charstripping db, and do a bogus wildcard expansion
|
||||
// (there is no wild card) to generate the result:
|
||||
if (diac_sensitive && case_sensitive) {
|
||||
// No expansion whatsoever
|
||||
m_db.termMatch(Rcl::Db::ET_WILD, m_stemlang, term, res, -1,
|
||||
m_field);
|
||||
} else {
|
||||
// Access case and diacritics expansion:
|
||||
vector<string> exp;
|
||||
SynTermTransUnac unacfoldtrans(UNACOP_UNACFOLD);
|
||||
XapComputableSynFamMember synac(m_db.m_ndb->xrdb, synFamDiCa,
|
||||
"all", &unacfoldtrans);
|
||||
oexp.push_back(prefix + term);
|
||||
LOGDEB(("ExpandTerm: final: %s\n", stringsToString(oexp).c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (diac_sensitive) {
|
||||
// Expand for accents and case, filtering for same accents,
|
||||
// then bogus wildcard expansion for generating result
|
||||
SynTermTransUnac foldtrans(UNACOP_FOLD);
|
||||
synac.synExpand(term, exp, &foldtrans);
|
||||
for (vector<string>::const_iterator it = exp.begin();
|
||||
it != exp.end(); it++) {
|
||||
m_db.termMatch(Rcl::Db::ET_WILD, m_stemlang, *it, res,
|
||||
-1, m_field);
|
||||
}
|
||||
} else if (case_sensitive) {
|
||||
// Expand for accents and case, filtering for same case,
|
||||
// then bogus wildcard expansion for generating result
|
||||
SynTermTransUnac unactrans(UNACOP_UNAC);
|
||||
synac.synExpand(term, exp, &unactrans);
|
||||
for (vector<string>::const_iterator it = exp.begin();
|
||||
it != exp.end(); it++) {
|
||||
m_db.termMatch(Rcl::Db::ET_WILD, m_stemlang, *it, res,
|
||||
-1, m_field);
|
||||
}
|
||||
} else {
|
||||
// Expand for accents and case, then lowercase
|
||||
// result for input to stemdb.
|
||||
synac.synExpand(term, exp);
|
||||
for (unsigned int i = 0; i < exp.size(); i++) {
|
||||
string lower;
|
||||
unacmaybefold(exp[i], lower, "UTF-8", UNACOP_FOLD);
|
||||
exp[i] = lower;
|
||||
}
|
||||
sort(exp.begin(), exp.end());
|
||||
vector<string>::iterator uit =
|
||||
unique(exp.begin(), exp.end());
|
||||
exp.resize(uit - exp.begin());
|
||||
LOGDEB(("ExpandTerm: after casediac: %s\n",
|
||||
stringsToString(exp).c_str()));
|
||||
SynTermTransUnac unacfoldtrans(UNACOP_UNACFOLD);
|
||||
XapComputableSynFamMember synac(m_db.m_ndb->xrdb, synFamDiCa, "all",
|
||||
&unacfoldtrans);
|
||||
vector<string> lexp;
|
||||
|
||||
StemDb db(m_db.m_ndb->xrdb);
|
||||
vector<string> exp1;
|
||||
for (vector<string>::const_iterator it = exp.begin();
|
||||
it != exp.end(); it++) {
|
||||
db.stemExpand(m_stemlang, *it, exp1);
|
||||
}
|
||||
LOGDEB(("ExpandTerm: after stem: %s\n",
|
||||
stringsToString(exp1).c_str()));
|
||||
|
||||
// Expand the resulting list for case (all stemdb content
|
||||
// is lowercase)
|
||||
exp.clear();
|
||||
for (vector<string>::const_iterator it = exp1.begin();
|
||||
it != exp1.end(); it++) {
|
||||
synac.synExpand(*it, exp);
|
||||
}
|
||||
sort(exp.begin(), exp.end());
|
||||
uit = unique(exp.begin(), exp.end());
|
||||
exp.resize(uit - exp.begin());
|
||||
|
||||
LOGDEB(("ExpandTerm: after case exp of stem: %s\n",
|
||||
stringsToString(exp).c_str()));
|
||||
|
||||
// Bogus wildcard expand to generate the result
|
||||
for (vector<string>::const_iterator it = exp.begin();
|
||||
it != exp.end(); it++) {
|
||||
m_db.termMatch(Rcl::Db::ET_WILD, m_stemlang, *it, res,
|
||||
-1, m_field);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (vector<TermMatchEntry>::const_iterator it = res.entries.begin();
|
||||
it != res.entries.end(); it++) {
|
||||
exp.push_back(it->term);
|
||||
}
|
||||
LOGDEB(("ExpandTerm: final: %s\n", stringsToString(exp).c_str()));
|
||||
TermMatchResult res;
|
||||
if (haswild) {
|
||||
// Note that if there are wildcards, we do a direct from-index
|
||||
// expansion, which means that we are casediac-sensitive. There
|
||||
// would be nothing to prevent us to expand from the casediac
|
||||
// synonyms first. To be done later
|
||||
m_db.termMatch(Rcl::Db::ET_WILD, m_stemlang, term, res, -1,
|
||||
m_field);
|
||||
goto termmatchtoresult;
|
||||
}
|
||||
|
||||
sterm = term;
|
||||
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
|
||||
m_db.termMatch(Rcl::Db::ET_STEM, m_stemlang, term, res, -1, m_field);
|
||||
|
||||
#else
|
||||
|
||||
if (o_index_stripchars) {
|
||||
// If the index is raw, we can only come here if nostemexp is unset
|
||||
// and we just need stem expansion.
|
||||
m_db.termMatch(Rcl::Db::ET_STEM, m_stemlang, term, res, -1, m_field);
|
||||
goto termmatchtoresult;
|
||||
}
|
||||
|
||||
// No stem expansion when diacritic or case sensitivity is set, it
|
||||
// makes no sense (it would mess with the diacritics anyway if
|
||||
// they are not in the stem part). In these 3 cases, perform
|
||||
// appropriate expansion from the charstripping db, and do a bogus
|
||||
// wildcard expansion (there is no wild card) to generate the
|
||||
// result:
|
||||
|
||||
if (diac_sensitive && case_sensitive) {
|
||||
// No expansion whatsoever
|
||||
m_db.termMatch(Rcl::Db::ET_WILD, m_stemlang, term, res, -1, m_field);
|
||||
goto termmatchtoresult;
|
||||
}
|
||||
|
||||
if (diac_sensitive) {
|
||||
// Expand for accents and case, filtering for same accents,
|
||||
// then bogus wildcard expansion for generating result
|
||||
SynTermTransUnac foldtrans(UNACOP_FOLD);
|
||||
synac.synExpand(term, lexp, &foldtrans);
|
||||
goto exptotermatch;
|
||||
}
|
||||
|
||||
if (case_sensitive) {
|
||||
// Expand for accents and case, filtering for same case, then
|
||||
// bogus wildcard expansion for generating result
|
||||
SynTermTransUnac unactrans(UNACOP_UNAC);
|
||||
synac.synExpand(term, lexp, &unactrans);
|
||||
goto exptotermatch;
|
||||
}
|
||||
|
||||
// We are neither accent- nor case- sensitive and may need stem
|
||||
// expansion or not.
|
||||
|
||||
// Expand for accents and case
|
||||
synac.synExpand(term, lexp);
|
||||
LOGDEB(("ExpTerm: casediac: %s\n", stringsToString(lexp).c_str()));
|
||||
if (nostemexp)
|
||||
goto exptotermatch;
|
||||
|
||||
// Need stem expansion. Lowercase the result of accent and case
|
||||
// expansion for input to stemdb.
|
||||
for (unsigned int i = 0; i < lexp.size(); i++) {
|
||||
string lower;
|
||||
unacmaybefold(lexp[i], lower, "UTF-8", UNACOP_FOLD);
|
||||
lexp[i] = lower;
|
||||
}
|
||||
sort(lexp.begin(), lexp.end());
|
||||
{
|
||||
vector<string>::iterator uit = unique(lexp.begin(), lexp.end());
|
||||
lexp.resize(uit - lexp.begin());
|
||||
StemDb db(m_db.m_ndb->xrdb);
|
||||
vector<string> exp1;
|
||||
for (vector<string>::const_iterator it = lexp.begin();
|
||||
it != lexp.end(); it++) {
|
||||
db.stemExpand(m_stemlang, *it, exp1);
|
||||
}
|
||||
LOGDEB(("ExpTerm: stem: %s\n", stringsToString(exp1).c_str()));
|
||||
|
||||
// Expand the resulting list for case (all stemdb content
|
||||
// is lowercase)
|
||||
lexp.clear();
|
||||
for (vector<string>::const_iterator it = exp1.begin();
|
||||
it != exp1.end(); it++) {
|
||||
synac.synExpand(*it, lexp);
|
||||
}
|
||||
sort(lexp.begin(), lexp.end());
|
||||
uit = unique(lexp.begin(), lexp.end());
|
||||
lexp.resize(uit - lexp.begin());
|
||||
}
|
||||
LOGDEB(("ExpTerm: case exp of stem: %s\n", stringsToString(lexp).c_str()));
|
||||
|
||||
// Bogus wildcard expand to generate the result
|
||||
exptotermatch:
|
||||
for (vector<string>::const_iterator it = lexp.begin();
|
||||
it != lexp.end(); it++) {
|
||||
m_db.termMatch(Rcl::Db::ET_WILD, m_stemlang, *it,
|
||||
res, -1, m_field);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Term match entries to vector of terms
|
||||
termmatchtoresult:
|
||||
for (vector<TermMatchEntry>::const_iterator it = res.entries.begin();
|
||||
it != res.entries.end(); it++) {
|
||||
oexp.push_back(it->term);
|
||||
}
|
||||
LOGDEB(("ExpandTerm: final: %s\n", stringsToString(oexp).c_str()));
|
||||
}
|
||||
|
||||
// Do distribution of string vectors: a,b c,d -> a,c a,d b,c b,d
|
||||
@@ -1097,9 +1125,11 @@ bool StringToXapianQ::processUserString(const string &iq,
|
||||
TermProcStop tpstop(nxt, stops); nxt = &tpstop;
|
||||
//TermProcCommongrams tpcommon(nxt, stops); nxt = &tpcommon;
|
||||
//tpcommon.onlygrams(true);
|
||||
#ifdef RCL_INDEX_STRIPCHARS
|
||||
TermProcPrep tpprep(nxt); nxt = &tpprep;
|
||||
TermProcPrep tpprep(nxt);
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
if (o_index_stripchars)
|
||||
#endif
|
||||
nxt = &tpprep;
|
||||
|
||||
TextSplitQ splitter(TextSplit::Flags(TextSplit::TXTS_ONLYSPANS |
|
||||
TextSplit::TXTS_KEEPWILD),
|
||||
|
||||
+15
-14
@@ -26,6 +26,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include <xapian.h>
|
||||
|
||||
@@ -34,18 +36,14 @@
|
||||
#include "smallut.h"
|
||||
#include "synfamily.h"
|
||||
#include "unacpp.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
#include "rclconfig.h"
|
||||
|
||||
namespace Rcl {
|
||||
|
||||
/**
|
||||
* Expand for one or several languages
|
||||
*/
|
||||
bool StemDb::stemExpand(const std::string& langs,
|
||||
const std::string& term,
|
||||
bool StemDb::stemExpand(const std::string& langs, const std::string& term,
|
||||
vector<string>& result)
|
||||
{
|
||||
vector<string> llangs;
|
||||
@@ -59,14 +57,17 @@ bool StemDb::stemExpand(const std::string& langs,
|
||||
}
|
||||
|
||||
#ifndef RCL_INDEX_STRIPCHARS
|
||||
for (vector<string>::const_iterator it = llangs.begin();
|
||||
it != llangs.end(); it++) {
|
||||
SynTermTransStem stemmer(*it);
|
||||
XapComputableSynFamMember expander(getdb(), synFamStemUnac,
|
||||
*it, &stemmer);
|
||||
string unac;
|
||||
unacmaybefold(term, unac, "UTF-8", UNACOP_UNAC);
|
||||
(void)expander.synExpand(unac, result);
|
||||
// Expand the unaccented stem
|
||||
if (!o_index_stripchars) {
|
||||
for (vector<string>::const_iterator it = llangs.begin();
|
||||
it != llangs.end(); it++) {
|
||||
SynTermTransStem stemmer(*it);
|
||||
XapComputableSynFamMember expander(getdb(), synFamStemUnac,
|
||||
*it, &stemmer);
|
||||
string unac;
|
||||
unacmaybefold(term, unac, "UTF-8", UNACOP_UNAC);
|
||||
(void)expander.synExpand(unac, result);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user