query-parser: special-case wildcards

We were transforming wild-card searches into regular-expression
searches; while that works, it's also significantly slower.

So, instead, special-case wildcards, and use the Xapian machinery for
wildcard queries.
This commit is contained in:
djcb
2018-05-18 15:55:40 +03:00
parent 84376b4aa7
commit 6290e4ad9a
2 changed files with 16 additions and 9 deletions

View File

@ -167,14 +167,9 @@ data (Mux::Tokens& tokens, ProcPtr proc, WarningVec& warnings)
} }
// does it look like a regexp? // does it look like a regexp?
if (val.length()>=2) { if (val.length() >=2 )
if (val[0]=='/' && val[val.length()-1] == '/') if (val[0] == '/' && val[val.length()-1] == '/')
return regex (fields, val, token.pos, proc, warnings); return regex (fields, val, token.pos, proc, warnings);
else if (val[val.length()-1] == '*')
return regex (fields, // transfrom wildcard into regexp
"/" + val.substr(0, val.length()-1) + ".*/",
token.pos, proc, warnings);
}
// does it look like a range? // does it look like a range?
const auto dotdot = val.find(".."); const auto dotdot = val.find("..");

View File

@ -48,18 +48,30 @@ xapian_query_op (const Mux::Tree& tree)
return Xapian::Query(op, childvec.begin(), childvec.end()); return Xapian::Query(op, childvec.begin(), childvec.end());
} }
static Xapian::Query
maybe_wildcard (const Value* val, const std::string& str)
{
const auto vlen = str.length();
if (vlen <= 1 || str[vlen-1] != '*')
return Xapian::Query(val->prefix + str);
else
return Xapian::Query(Xapian::Query::OP_WILDCARD,
val->prefix + str.substr(0, vlen-1));
}
static Xapian::Query static Xapian::Query
xapian_query_value (const Mux::Tree& tree) xapian_query_value (const Mux::Tree& tree)
{ {
const auto v = dynamic_cast<Value*> (tree.node.data.get()); const auto v = dynamic_cast<Value*> (tree.node.data.get());
if (!v->phrase) if (!v->phrase)
return Xapian::Query(v->prefix + v->value); return maybe_wildcard(v, v->value);
const auto parts = split (v->value, " "); const auto parts = split (v->value, " ");
std::vector<Xapian::Query> phvec; std::vector<Xapian::Query> phvec;
for (const auto p: parts) for (const auto p: parts)
phvec.push_back(Xapian::Query(v->prefix + p)); phvec.emplace_back(maybe_wildcard(v, p));
if (parts.empty()) if (parts.empty())
return Xapian::Query::MatchNothing; // shouldn't happen return Xapian::Query::MatchNothing; // shouldn't happen