66 #include <string_view>
67 #include <unordered_set>
93 #if (defined(__i386__) && !defined(__SSE_MATH__)) || \
94 defined(__mc68000__) || defined(__mc68010__) || \
95 defined(__mc68020__) || defined(__mc68030__)
118 return a_max_wt > b_max_wt;
152 : qopt(qopt_), estimates(reserve) {
165 if (termfreqs) termfreqs_list.emplace_back(*termfreqs);
170 add_termfreqs(termfreqs);
172 pls.emplace_back(pl);
174 if (estimate) estimates.
push_back(estimate);
181 first = std::min(first, f);
182 last = std::max(last, l);
189 add_postlist(
p.pl,
p.est.release(), termfreqs);
202 if (new_size >= pls.size())
205 for (
auto&& i = pls.begin() + new_size; i != pls.end(); ++i) {
208 pls.resize(new_size);
209 estimates.
erase(estimates.
begin() + new_size, estimates.
end());
228 unique_ptr<TermList> t(qopt->db.open_allterms(
query->get_fixed_prefix()));
229 bool skip_ucase =
query->get_fixed_prefix().
empty();
230 auto max_type =
query->get_max_type();
234 if (expansions_left == 0)
235 expansions_left = numeric_limits<decltype(expansions_left)>::max();
247 const string &
term = t->get_termname();
248 if (skip_ucase &&
term[0] >=
'A') {
257 if (
term[0] <=
'Z') {
258 static_assert(
'Z' + 1 ==
'[',
"'Z' + 1 == '['");
264 if (!
query->test_prefix_known(
term))
continue;
267 if (expansions_left == 0) {
270 string msg(
"Wildcard ");
271 msg +=
query->get_pattern();
272 if (
query->get_just_flags() == 0)
274 msg +=
" expands to more than ";
275 msg +=
str(
query->get_max_expansion());
282 add_postlist(qopt->open_lazy_post_list(
term, 1, factor), NULL);
288 auto set_size =
query->get_max_expansion();
289 if (size() > set_size) {
290 auto begin = pls.begin();
291 nth_element(begin, begin + set_size - 1, pls.end(),
298 for (
auto pl : pls) {
303 qopt->register_lazy_postlist_for_stats(
static_cast<LeafPostList*
>(pl),
305 add_termfreqs(termfreqs);
314 string pfx(
query->get_pattern(), 0,
query->get_fixed_prefix_len());
315 unique_ptr<TermList> t(qopt->db.open_allterms(pfx));
316 bool skip_ucase = pfx.empty();
317 auto max_type =
query->get_max_type();
321 if (expansions_left == 0)
322 expansions_left = numeric_limits<decltype(expansions_left)>::max();
334 const string&
term = t->get_termname();
337 if (skip_ucase &&
term[0] >=
'A') {
345 if (
term[0] <=
'Z') {
346 static_assert(
'Z' + 1 ==
'[',
"'Z' + 1 == '['");
355 if (expansions_left == 0) {
358 string msg(
"Edit distance ");
359 msg +=
query->get_pattern();
362 msg +=
" expands to more than ";
363 msg +=
str(
query->get_max_expansion());
370 add_postlist(qopt->open_lazy_post_list(
term, 1, factor), NULL);
374 auto set_size =
query->get_max_expansion();
375 if (size() > set_size) {
376 auto begin = pls.begin();
377 nth_element(begin, begin + set_size - 1, pls.end(),
384 for (
auto pl : pls) {
386 qopt->register_lazy_postlist_for_stats(
static_cast<LeafPostList*
>(pl),
388 add_termfreqs(termfreqs);
397 void estimate_termfreqs(
TermFreqs* termfreqs);
400 void select_elite_set(
size_t set_size,
size_t out_of);
412 Assert(!termfreqs_list.empty());
417 const TermFreqs& freqs = termfreqs_list[0];
418 auto& stats = *qopt->get_stats();
421 Assert(stats.collection_size);
422 double scale = 1.0 / stats.collection_size;
423 double P_est = freqs.
termfreq * scale;
424 double rtf_scale = 0.0;
425 if (stats.rset_size != 0) {
426 rtf_scale = 1.0 / stats.rset_size;
430 double cf_scale = 0.0;
431 if (
usual(stats.total_length != 0)) {
432 cf_scale = 1.0 / stats.total_length;
434 double Pc_est = freqs.
collfreq * cf_scale;
436 for (
size_t i = 1; i < termfreqs_list.size(); ++i) {
439 P_est += P_i - P_est * P_i;
440 double Pc_i = f.
collfreq * cf_scale;
441 Pc_est += Pc_i - Pc_est * Pc_i;
444 if (stats.rset_size != 0) {
446 Pr_est += Pr_i - Pr_est * Pr_i;
457 OrContext::select_elite_set(
size_t set_size,
size_t out_of)
459 auto begin = pls.begin() + pls.size() - out_of;
460 nth_element(begin, begin + set_size - 1, pls.end(),
CmpMaxOrTerms());
461 shrink(pls.size() - out_of + set_size);
467 if (!termfreqs_list.empty()) estimate_termfreqs(termfreqs);
469 switch (pls.size()) {
476 return {pl, estimates.empty() ? nullptr : estimates.release_at(0)};
480 unique_ptr<EstimateOp> est;
481 if (!qopt->get_no_estimates()) {
483 std::move(estimates)));
487 auto pl =
new BoolOrPostList(pls.begin(), pls.end(), qopt->db_size);
490 return {pl, std::move(est)};
514 auto pl =
new OrPostList(pls.front(), r, qopt->matcher);
516 if (pls.size() == 1) {
518 return {pl, std::move(est)};
528 OrContext::postlist_max()
530 switch (pls.size()) {
536 return {pl, estimates.release_at(0)};
545 qopt->matcher, qopt->db_size);
546 unique_ptr<EstimateOp> est;
547 if (!qopt->get_no_estimates()) {
550 std::move(estimates)));
553 return {pl, std::move(est)};
571 Assert(!termfreqs_list.empty());
576 auto& stats = *qopt->get_stats();
577 const TermFreqs& freqs = termfreqs_list[0];
580 Assert(stats.collection_size);
581 double scale = 1.0 / stats.collection_size;
582 double P_est = freqs.
termfreq * scale;
583 double rtf_scale = 0.0;
584 if (stats.rset_size != 0) {
585 rtf_scale = 1.0 / stats.rset_size;
589 double cf_scale = 0.0;
590 if (
usual(stats.total_length != 0)) {
591 cf_scale = 1.0 / stats.total_length;
593 double Pc_est = freqs.
collfreq * cf_scale;
595 for (
size_t i = 1; i < termfreqs_list.size(); ++i) {
598 P_est += P_i - 2.0 * P_est * P_i;
599 double Pc_i = f.
collfreq * cf_scale;
600 Pc_est += Pc_i - 2.0 * Pc_est * Pc_i;
603 if (stats.rset_size != 0) {
605 Pr_est += Pr_i - 2.0 * Pr_est * Pr_i;
615 unique_ptr<EstimateOp> est;
616 if (!qopt->get_no_estimates()) {
618 std::move(estimates)));
620 auto pl =
new XorPostList(pls.begin(), pls.end(), qopt->matcher,
624 return {pl, std::move(est)};
638 : op_(op__), begin(begin_), end(end_), window(window_) { }
642 const vector<PostList*>& pls,
646 auto terms_begin = pls.begin() + begin;
647 auto terms_end = pls.begin() + end;
650 if (termfreqs) *termfreqs /= 2;
655 window, terms_begin, terms_end, pltree);
656 }
else if (window != end - begin) {
658 if (termfreqs) *termfreqs /= 3;
663 window, terms_begin, terms_end, pltree);
666 if (termfreqs) *termfreqs /= 4;
671 terms_begin, terms_end, pltree);
693 bool match_all =
false;
704 add_termfreqs(termfreqs);
706 if (pls.empty() && termfreqs_list.size() > 1) {
707 qopt->destroy_postlist(pl);
710 pls.emplace_back(pl);
711 estimates.push_back(estimate.release());
714 first = std::max(first, pl_first);
715 last = std::min(last, pl_last);
722 return termfreqs != NULL;
726 return add_postlist(
p.pl, std::move(
p.est), termfreqs);
737 not_ctx.reset(
new OrContext(qopt, reserve));
744 maybe_ctx.reset(
new OrContext(qopt, reserve));
758 size_t end = pls.size();
759 size_t begin = end - n_subqs;
760 pos_filters.push_back(
PosFilter(op_, begin, end, window));
763 template<
typename T,
typename U>
771 return static_cast<T
>((l * double(n - r)) / n + 0.5);
777 auto matcher = qopt->matcher;
778 auto db_size = qopt->db_size;
781 Assert(!termfreqs_list.empty());
786 const TermFreqs& freqs = termfreqs_list[0];
788 double freqest = double(freqs.
termfreq);
790 double collfreqest = double(freqs.
collfreq);
792 auto& stats = *qopt->get_stats();
795 Assert(stats.collection_size);
797 for (
size_t i = 1; i < termfreqs_list.size(); ++i) {
802 freqest *= f.
termfreq / stats.collection_size;
803 if (
usual(stats.total_length != 0)) {
804 collfreqest *= f.
collfreq / stats.total_length;
809 if (stats.rset_size != 0)
819 unique_ptr<PostList> pl;
820 unique_ptr<EstimateOp> est;
821 switch (pls.size()) {
828 auto [new_pl, new_est] = qopt->open_post_list({}, 0, 0.0,
nullptr);
830 est = std::move(new_est);
835 est.reset(estimates.release_at(0));
838 pl.reset(
new AndPostList(pls.begin(), pls.end(), matcher));
839 if (!qopt->get_no_estimates()) {
841 std::move(estimates)));
846 if (not_ctx && !not_ctx->empty()) {
847 if (not_ctx->get_last() < first || not_ctx->get_first() > last) {
853 auto [rhs, rhs_est] = not_ctx->postlist(termfreqs ? &r_freqs : NULL,
857 auto& stats = *qopt->get_stats();
860 Assert(stats.collection_size);
863 stats.collection_size);
868 if (stats.total_length != 0) {
876 if (stats.rset_size != 0) {
884 if (!qopt->get_no_estimates()) {
887 std::move(est), std::move(rhs_est)));
898 for (
const PosFilter& filter : pos_filters) {
899 auto [new_pl, new_est] = filter.postlist(pl.release(), est.release(),
900 pls, matcher, termfreqs);
902 est = std::move(new_est);
908 if (maybe_ctx && !maybe_ctx->empty()) {
909 if (maybe_ctx->get_last() < first || maybe_ctx->get_first() > last) {
920 bool save_no_estimates = qopt->get_no_estimates();
921 qopt->set_no_estimates(
true);
922 auto [rhs, rhs_est] = maybe_ctx->postlist(termfreqs);
923 qopt->set_no_estimates(save_no_estimates);
939 return {pl.release(), est.release()};
944 Query::Internal::~Internal() { }
947 Query::Internal::get_num_subqueries() const noexcept
953 Query::Internal::get_subquery(
size_t)
const
959 Query::Internal::get_wqf()
const
965 Query::Internal::get_pos()
const
971 Query::Internal::gather_terms(
void *)
const
976 Query::Internal::get_length() const noexcept
982 Query::Internal::unserialise(
const char **
p,
const char * end,
987 unsigned char ch = *(*p)++;
989 case 4:
case 5:
case 6:
case 7: {
995 size_t n_subqs = ch & 0x07;
1002 unsigned char code = (ch >> 3) & 0x0f;
1053 }
while (--n_subqs);
1067 size_t len = ch & 0x0f;
1074 if (
size_t(end - *
p) < len)
1076 string term(*
p, len);
1079 int code = ((ch >> 4) & 0x03);
1135 switch (ch & 0x1f) {
1143 int flags =
static_cast<unsigned char>(*(*p)++);
1144 op combiner =
static_cast<op>(*(*p)++);
1145 unsigned edit_distance;
1146 size_t fixed_prefix_len;
1154 return new QueryEditDistance(pattern,
1166 int flags =
static_cast<unsigned char>(*(*p)++);
1167 op combiner =
static_cast<op>(*(*p)++);
1185 string m =
"PostingSource ";
1187 m +=
" not registered";
1191 string serialised_source;
1203 return new QueryScaleWeight(scale_factor,
1204 Query(unserialise(
p, end, reg)));
1223 string msg =
"Unknown Query serialisation: ";
1234 return ctx.
add_postlist(postlist(qopt, factor, termfreqs), termfreqs);
1242 bool keep_zero_weight)
const
1245 auto [pl_, est] = postlist(qopt, factor, termfreqs);
1246 unique_ptr<PostList> pl{pl_};
1247 if (!keep_zero_weight && pl && pl->recalc_maxweight() == 0.0) {
1257 ctx.
add_postlist(pl.release(), est.release(), termfreqs);
1265 ctx.
add_postlist(postlist(qopt, 0.0, termfreqs), termfreqs);
1274 ctx.
add_postlist(postlist(qopt, factor, termfreqs), termfreqs);
1280 QueryTerm::get_type() const noexcept
1282 return term.empty() ? Query::LEAF_MATCH_ALL : Query::LEAF_TERM;
1286 QueryTerm::get_description()
const
1290 desc =
"<alldocuments>";
1310 if (
source->_refs == 0) {
1328 string desc =
"PostingSource(";
1329 desc +=
source->get_description();
1335 : scale_factor(factor), subquery(subquery_)
1401 unique_ptr<EstimateOp> est;
1419 double termfreq = pl->get_termfreq();
1420 auto tf = termfreq * stats.collection_size / db_size;
1421 auto rtf = termfreq * stats.rset_size / db_size;
1422 auto cf = termfreq * stats.total_length / db_size;
1427 RETURN({pl, std::move(est)});
1453 if (!
term.empty()) {
1454 vector<pair<Xapian::termpos, string>> &terms =
1455 *
static_cast<vector<pair<Xapian::termpos, string>
>*>(void_terms);
1456 terms.push_back(make_pair(
pos,
term));
1465 for (
size_t i = prefix; i != s.size(); ++i) {
1467 r +=
static_cast<unsigned char>(s[i]) * f;
1475 const string& begin,
const string* end,
1482 size_t common_prefix_len = size_t(-1);
1487 if (common_prefix_len == lo.size()) {
1488 if (common_prefix_len != hi.size())
1494 Assert(begin <= lo && (!end || hi <= *end));
1497 AssertRel(common_prefix_len, !=, hi.size());
1498 }
while (lo[common_prefix_len] == hi[common_prefix_len]);
1502 double denom = h - l;
1503 if (
rare(denom == 0.0)) {
1511 Assert(!(begin <= lo && (!end || hi <= *end)));
1516 return value_freq / 2;
1524 if (end && *end < hi) {
1529 double est = (e - b) / denom * value_freq;
1541 const auto db_size = qopt->
db_size;
1549 if (termfreqs) *termfreqs =
TermFreqs();
1553 if (termfreqs) *termfreqs =
TermFreqs();
1558 if (termfreqs) *termfreqs =
TermFreqs();
1565 auto cf = clamp_cast<Xapian::termcount>(stats.total_length);
1566 *termfreqs =
TermFreqs(stats.collection_size,
1577 unique_ptr<EstimateOp> est;
1580 if (value_freq == db_size) {
1590 if (termfreqs) *termfreqs *= double(value_freq) / db_size;
1592 value_freq,
slot,
string());
1593 RETURN({pl, std::move(est)});
1596 unique_ptr<EstimateOp> est;
1599 if (termfreqs) *termfreqs *= double(tf_est) / db_size;
1601 RETURN({pl, std::move(est)});
1604 unique_ptr<EstimateOp> est;
1607 if (termfreqs) *termfreqs *= double(tf_est) / db_size;
1609 RETURN({pl, std::move(est)});
1616 result +=
static_cast<char>(0x20 |
slot);
1618 result +=
static_cast<char>(0x20 | 15);
1634 string desc =
"VALUE_RANGE ";
1651 const auto db_size = qopt->
db_size;
1659 if (termfreqs) *termfreqs =
TermFreqs();
1663 if (termfreqs) *termfreqs =
TermFreqs();
1670 auto cf = clamp_cast<Xapian::termcount>(stats.total_length);
1671 *termfreqs =
TermFreqs(stats.collection_size,
1682 unique_ptr<EstimateOp> est;
1685 if (value_freq == db_size) {
1695 if (termfreqs) *termfreqs *= double(value_freq) / db_size;
1697 value_freq,
slot,
string());
1698 RETURN({pl, std::move(est)});
1701 unique_ptr<EstimateOp> est;
1704 if (termfreqs) *termfreqs *= double(tf_est) / db_size;
1707 RETURN({pl, std::move(est)});
1716 result +=
static_cast<char>(0x20 |
slot);
1718 result +=
static_cast<char>(0x20 | 15);
1734 string desc =
"VALUE_LE ";
1749 const auto db_size = qopt->
db_size;
1757 if (termfreqs) *termfreqs =
TermFreqs();
1762 if (termfreqs) *termfreqs =
TermFreqs();
1769 auto cf = clamp_cast<Xapian::termcount>(stats.total_length);
1770 *termfreqs =
TermFreqs(stats.collection_size,
1780 unique_ptr<EstimateOp> est;
1783 if (value_freq == db_size) {
1794 value_freq,
slot,
string());
1795 RETURN({pl, std::move(est)});
1798 unique_ptr<EstimateOp> est;
1801 if (termfreqs) *termfreqs *= double(tf_est) / db_size;
1803 RETURN({pl, std::move(est)});
1810 result +=
static_cast<char>(0x20 | 0x10 |
slot);
1812 result +=
static_cast<char>(0x20 | 0x10 | 15);
1827 string desc =
"VALUE_GE ";
1838 : pattern(pattern_),
1839 max_expansion(max_expansion_),
1872 size_t qm_count = 0;
1873 bool had_star =
false;
1915 }
else if (qm_count > 1) {
1920 }
else if (qm_count == 1) {
1937 for ( ; i !=
tail; ++i) {
1943 for (
size_t test_o = o; test_o <=
p; ++test_o) {
1949 if (o ==
p)
return false;
1951 unsigned char b = candidate[o];
1959 }
else if (b < 0xf0) {
1964 if (
rare(
p - o < seqlen))
return false;
1969 if (
pattern[i] != candidate[o])
return false;
1978 if (candidate.size() <
min_len)
return false;
1979 if (candidate.size() >
max_len)
return false;
1985 candidate.size() -
suffix.size(),
1997 if (factor == 0.0) {
2004 if (!old_compound_weight) {
2027 factor, synonym_freqs));
2056 result +=
static_cast<char>(0x0b);
2058 result +=
static_cast<unsigned char>(
flags);
2059 result +=
static_cast<unsigned char>(
combiner);
2072 string desc =
"WILDCARD ";
2095 int edist =
edcalc(candidate, threshold);
2096 return edist <= threshold ? edist + 1 : 0;
2107 if (factor == 0.0) {
2114 if (!old_compound_weight) {
2137 factor, synonym_freqs));
2166 result +=
static_cast<char>(0x0a);
2168 result +=
static_cast<unsigned char>(
flags);
2169 result +=
static_cast<unsigned char>(
combiner);
2184 string desc =
"EDIT_DISTANCE ";
2203 desc +=
" fixed_prefix_len=";
2219 result += (*i).internal->get_length();
2224 #define MULTIWAY(X) static_cast<unsigned char>(0x80 | (X) << 3)
2225 #define MISC(X) static_cast<unsigned char>(X)
2229 static const unsigned char first_byte[] = {
2247 AssertRel(
size_t(op_),<,
sizeof(first_byte));
2248 unsigned char ch = first_byte[op_];
2266 (*i).internal->serialise(result);
2308 (*i).internal->gather_terms(void_terms);
2318 LOGCALL_VOID(MATCH,
"QueryBranch::do_bool_or_like", ctx | qopt | termfreqs | first);
2331 (*q).internal->postlist_sub_bool_or_like(ctx, qopt, termfreqs);
2339 bool keep_zero_weight)
const
2341 LOGCALL_VOID(MATCH,
"QueryBranch::do_or_like", ctx | qopt | factor | termfreqs | elite_set_size | first | keep_zero_weight);
2350 size_t size_before = ctx.
size();
2355 (*q).internal->postlist_sub_or_like(ctx, qopt, factor,
2360 size_t out_of = ctx.
size() - size_before;
2361 if (elite_set_size && elite_set_size < out_of) {
2382 if (factor == 0.0) {
2388 return ctx.
postlist(termfreqs,
true);
2392 Assert(!old_compound_weight);
2398 if (!plest.
pl)
return {};
2418 if (factor == 0.0) {
2461 if (desc.size() > 1) {
2464 desc +=
str(parameter);
2472 desc += (*i).internal->get_description();
2495 size_t len =
term.size();
2497 if (
wqf == 1 &&
pos == 0) {
2506 }
else if (
wqf == 1) {
2510 result +=
static_cast<char>(0x40 | 0x10);
2513 result +=
static_cast<char>(0x40 | 0x10 | len);
2519 result +=
static_cast<char>(0x40 | 0x20);
2522 result +=
static_cast<char>(0x40 | 0x20 | len);
2527 }
else if (
wqf > 1 ||
pos > 0) {
2530 result +=
static_cast<char>(0x40 | 0x30);
2533 result +=
static_cast<char>(0x40 | 0x30 | len);
2543 result +=
static_cast<char>(0x40);
2546 result +=
static_cast<char>(0x40 | len);
2554 result +=
static_cast<char>(0x0c);
2615 if (!(*i).internal->postlist_sub_and_like(ctx, qopt, factor, termfreqs))
2715 if (factor == 0.0) {
2727 bool keep_zero_weight)
const
2729 do_or_like(ctx, qopt, factor, termfreqs, 0, 0, keep_zero_weight);
2761 if (!
subqueries[0].internal->postlist_sub_and_like(ctx, qopt, factor,
2789 (*i).internal->postlist_sub_xor(ctx, qopt, factor, termfreqs);
2814 if (!
subqueries[0].internal->postlist_sub_and_like(ctx, qopt, factor,
2820 if (factor != 0.0) {
2827 do_or_like(maybe_ctx, qopt, factor, termfreqs, 0, 1, need_wdf);
2855 if (!(*i).internal->postlist_sub_and_like(ctx, qopt, factor, termfreqs))
2894 result = ctx.
add_postlist(std::move(plest), termfreqs);
2896 if (factor == 0.0)
break;
2955 bool keep_zero_weight)
const
3147 string d =
"(SYNONYM ";
3148 d +=
subqueries[0].internal->get_description();
3176 result +=
static_cast<char>(0x00);
PostList class implementing Query::OP_AND_MAYBE.
PostList class implementing Query::OP_AND_NOT.
static Xapian::Query query(Xapian::Query::op op, const string &t1=string(), const string &t2=string(), const string &t3=string(), const string &t4=string(), const string &t5=string(), const string &t6=string(), const string &t7=string(), const string &t8=string(), const string &t9=string(), const string &t10=string())
PostList class implementing unweighted Query::OP_OR.
Cast a value to a type, clamping out of range values.
PostList class implementing Query::OP_AND_MAYBE.
PostList class implementing Query::OP_AND_NOT.
PostList class implementing unweighted Query::OP_OR.
Class for estimating the total number of matching documents.
Postlist which matches an exact phrase using positional information.
Abstract base class for leaf postlists.
N-way OR postlist with wt=max(wt_i).
Postlist which matches terms occurring within a specified window.
Wrapper postlist providing positions for an OR.
PostList class implementing Query::OP_OR.
Postlist which matches a phrase using positional information.
bool * get_max_weight_cached_flag_ptr()
Return pointer to flag to set to false to invalidate cached max weight.
Virtual base class for Database internals.
virtual std::string get_value_upper_bound(valueno slot) const =0
Get an upper bound on the values stored in the given value slot.
virtual std::string get_value_lower_bound(valueno slot) const =0
Get a lower bound on the values stored in the given value slot.
virtual PostList * open_post_list(std::string_view term) const =0
Return a PostList suitable for use in a PostingIterator.
virtual bool has_positions() const =0
Check whether this database contains any positional information.
virtual doccount get_value_freq(valueno slot) const =0
Return the frequency of a given value slot.
An indexed database of documents.
PostListAndEstimate postlist(TermFreqs *termfreqs)
bool add_postlist(PostList *pl, unique_ptr< EstimateOp > &&estimate, TermFreqs *termfreqs)
OrContext & get_maybe_ctx(size_t reserve)
AndContext(QueryOptimiser *qopt_, size_t reserve)
unique_ptr< OrContext > maybe_ctx
void add_pos_filter(Query::op op_, size_t n_subqs, Xapian::termcount window)
OrContext & get_not_ctx(size_t reserve)
bool add_postlist(PostListAndEstimate p, TermFreqs *termfreqs)
list< PosFilter > pos_filters
unique_ptr< OrContext > not_ctx
VecUniquePtr< EstimateOp > estimates
void add_postlist(PostList *pl, EstimateOp *estimate, TermFreqs *termfreqs)
vector< TermFreqs > termfreqs_list
Xapian::docid get_first() const
void expand_edit_distance(const QueryEditDistance *query, double factor, TermFreqs *termfreqs)
Expand an edit distance query.
Context(QueryOptimiser *qopt_, size_t reserve)
void add_termfreqs(TermFreqs *termfreqs)
void expand_wildcard(const QueryWildcard *query, double factor, TermFreqs *termfreqs)
Expand a wildcard query.
void add_postlist(PostListAndEstimate p, TermFreqs *termfreqs)
Xapian::docid get_last() const
Xapian::termcount size() const
void shrink(size_t new_size)
PostListAndEstimate postlist_max()
void select_elite_set(size_t set_size, size_t out_of)
Select the best set_size postlists from the last out_of added.
PostListAndEstimate postlist(TermFreqs *termfreqs, bool bool_or=false)
OrContext(QueryOptimiser *qopt_, size_t reserve)
size_t begin
Start and end indices for the PostLists this positional filter uses.
PostListAndEstimate postlist(PostList *pl, EstimateOp *est, const vector< PostList * > &pls, PostListTree *pltree, TermFreqs *termfreqs) const
PosFilter(Xapian::Query::op op__, size_t begin_, size_t end_, Xapian::termcount window_)
Abstract base class for postlists.
Xapian::doccount get_termfreq() const
Get an estimate of the number of documents this PostList will return.
virtual double recalc_maxweight()=0
Recalculate the upper bound on what get_weight() can return.
virtual void get_docid_range(docid &first, docid &last) const
Get the bounds on the range of docids this PostList can return.
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
bool postlist_sub_and_like(AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void add_subquery(const Xapian::Query &subquery)
bool postlist_sub_and_like(AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void add_subquery(const Xapian::Query &subquery)
Xapian::Query::op get_op() const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
std::string get_description() const
Xapian::Query::op get_op() const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
std::string get_description() const
void add_subquery(const Xapian::Query &subquery)
bool postlist_sub_and_like(AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
Xapian::Query::op get_op() const
std::string get_description() const
virtual Query::Internal * done()=0
void do_bool_or_like(OrContext &ctx, QueryOptimiser *qopt, TermFreqs *termfreqs, size_t first=0) const
void do_or_like(OrContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs, Xapian::termcount elite_set_size=0, size_t first=0, bool keep_zero_weight=true) const
Process OR-like subqueries.
virtual Xapian::Query::op get_op() const =0
void serialise_(std::string &result, Xapian::termcount parameter=0) const
virtual void add_subquery(const Xapian::Query &subquery)=0
Xapian::Query::op get_type() const noexcept
const std::string get_description_helper(const char *op, Xapian::termcount window=0) const
PostListAndEstimate do_max(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void gather_terms(void *void_terms) const
termcount get_length() const noexcept
PostListAndEstimate do_synonym(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
const Query get_subquery(size_t n) const
size_t get_num_subqueries() const noexcept
void serialise(std::string &result) const
Xapian::termcount max_expansion
void serialise(std::string &result) const
int test(const std::string &candidate) const
Perform edit distance test.
unsigned get_threshold() const
QueryEditDistance * change_combiner(Xapian::Query::op new_op)
Change the combining operator.
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
termcount get_length() const noexcept
Xapian::Query::op get_type() const noexcept
std::string get_description() const
EditDistanceCalculator edcalc
Xapian::termcount set_size
void serialise(std::string &result) const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void postlist_sub_or_like(OrContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs, bool keep_zero_weight) const
std::string get_description() const
Xapian::Query::op get_op() const
std::string get_description() const
bool postlist_sub_and_like(AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
Xapian::Query::op get_op() const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void serialise(std::string &result) const
Xapian::Query::op get_type() const noexcept
std::string get_description() const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
std::string get_description() const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
Xapian::Query::op get_op() const
void serialise(std::string &result) const
Xapian::Query::op get_op() const
std::string get_description() const
bool postlist_sub_and_like(AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
Xapian::doccount shard_index
Xapian::termcount get_total_subqs() const
void set_no_estimates(bool f)
bool need_wdf_for_compound_weight() const
void destroy_postlist(PostList *pl)
PostListAndEstimate open_post_list(const std::string &term, Xapian::termcount wqf, double factor, TermFreqs *termfreqs)
Create a PostList object for term.
PostListAndEstimate make_synonym_postlist(PostListAndEstimate or_pl, double factor, const TermFreqs &termfreqs)
Create a SynonymPostList object.
const Xapian::Weight::Internal * get_stats() const
bool get_no_estimates() const
const Xapian::Database::Internal & db
void set_total_subqs(Xapian::termcount n)
void add_subquery(const Xapian::Query &subquery)
Xapian::Query::op get_op() const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void postlist_sub_bool_or_like(OrContext &ctx, QueryOptimiser *qopt, TermFreqs *termfreqs) const
void postlist_sub_or_like(OrContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs, bool keep_zero_weight) const
std::string get_description() const
std::string get_description() const
Xapian::Query::op get_op() const
void serialise(std::string &result) const
bool postlist_sub_and_like(AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
Xapian::Internal::opt_intrusive_ptr< PostingSource > source
std::string get_description() const
Xapian::Query::op get_type() const noexcept
void serialise(std::string &result) const
void serialise(std::string &result) const
std::string get_description() const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
const Query get_subquery(size_t n) const
bool postlist_sub_and_like(AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
QueryScaleWeight(double factor, const Query &subquery_)
Xapian::Query::op get_type() const noexcept
void gather_terms(void *void_terms) const
size_t get_num_subqueries() const noexcept
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
Xapian::Query::op get_op() const
std::string get_description() const
void serialise(std::string &result) const
void gather_terms(void *void_terms) const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
bool postlist_sub_and_like(AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
Xapian::Query::op get_type() const noexcept
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
std::string get_description() const
void serialise(std::string &result) const
void serialise(std::string &result) const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
std::string get_description() const
Xapian::Query::op get_type() const noexcept
Xapian::Query::op get_type() const noexcept
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void serialise(std::string &result) const
std::string get_description() const
bool test_wildcard_(const std::string &candidate, size_t o, size_t p, size_t i) const
size_t head
Fixed head and tail lengths, and min/max length term that can match.
Xapian::termcount max_expansion
Xapian::Query::op get_type() const noexcept
QueryWildcard * change_combiner(Xapian::Query::op new_op)
Change the combining operator.
bool test_prefix_known(const std::string &candidate) const
Perform wildcard test on candidate known to match prefix.
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void serialise(std::string &result) const
QueryWildcard(std::string_view pattern_, Xapian::termcount max_expansion_, int flags_, Query::op combiner_)
std::string get_description() const
termcount get_length() const noexcept
bool postlist_windowed(Xapian::Query::op op, AndContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
PostListAndEstimate postlist(QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
void postlist_sub_xor(XorContext &ctx, QueryOptimiser *qopt, double factor, TermFreqs *termfreqs) const
std::string get_description() const
Xapian::Query::op get_op() const
PostListAndEstimate postlist(TermFreqs *termfreqs)
XorContext(QueryOptimiser *qopt_, size_t reserve)
InvalidArgumentError indicates an invalid parameter value was passed to the API.
InvalidOperationError indicates the API was used in an invalid way.
Base class which provides an "external" source of postings.
virtual PostingSource * unserialise_with_registry(const std::string &serialised, const Registry ®istry) const
Create object given string serialisation returned by serialise().
PostingSource * release()
Start reference counting this object.
Class representing a query.
const Query get_subquery(size_t n) const
Read a top level subquery.
op get_type() const noexcept
Get the type of the top level of the query.
@ OP_SCALE_WEIGHT
Scale the weight contributed by a subquery.
@ LEAF_POSTING_SOURCE
Value returned by get_type() for a PostingSource.
@ OP_MAX
Pick the maximum weight of any subquery.
@ OP_VALUE_RANGE
Match only documents where a value slot is within a given range.
@ OP_WILDCARD
Wildcard expansion.
@ OP_XOR
Match documents which an odd number of subqueries match.
@ OP_AND_MAYBE
Match the first subquery taking extra weight from other subqueries.
@ LEAF_MATCH_ALL
Value returned by get_type() for MatchAll or equivalent.
@ OP_NEAR
Match only documents where all subqueries match near each other.
@ OP_ELITE_SET
Pick the best N subqueries and combine with OP_OR.
@ OP_AND
Match only documents which all subqueries match.
@ OP_OR
Match documents which at least one subquery matches.
@ OP_FILTER
Match like OP_AND but only taking weight from the first subquery.
@ OP_PHRASE
Match only documents where all subqueries match near and in order.
@ OP_VALUE_LE
Match only documents where a value slot is <= a given value.
@ OP_SYNONYM
Match like OP_OR but weighting as if a single term.
@ OP_AND_NOT
Match documents which the first subquery matches but no others do.
@ OP_EDIT_DISTANCE
Edit distance expansion.
@ LEAF_TERM
Value returned by get_type() for a term.
@ OP_VALUE_GE
Match only documents where a value slot is >= a given value.
@ OP_INVALID
Construct an invalid query.
bool empty() const noexcept
Check if this query is Xapian::Query::MatchNothing.
@ WILDCARD_PATTERN_MULTI
Support * which matches 0 or more characters.
@ WILDCARD_LIMIT_FIRST
Stop expanding when OP_WILDCARD reaches its expansion limit.
@ WILDCARD_LIMIT_MOST_FREQUENT
Limit OP_WILDCARD expansion to the most frequent terms.
@ WILDCARD_PATTERN_SINGLE
Support ? which matches a single character.
Xapian::Internal::intrusive_ptr< Internal > internal
Registry for user subclasses.
const Xapian::PostingSource * get_posting_source(std::string_view name) const
Get a posting source given a name.
Indicates an error in the std::string serialisation of an object.
T::Internal *const * const_iterator
const_iterator begin() const
const_iterator end() const
void push_back(const T &elt)
Abstract base class for termlists.
virtual Internal * skip_to(std::string_view term)=0
Skip forward to the specified term.
virtual Internal * next()=0
Advance the current position to the next term in the termlist.
Suitable for "simple" type T.
const_iterator end() const
void reserve(size_type n)
void erase(const_iterator it)
const_iterator begin() const
WildcardError indicates an error expanding a wildcarded query.
#define UNSIGNED_OVERFLOW_OK(X)
#define LOGCALL(CATEGORY, TYPE, FUNC, PARAMS)
#define LOGCALL_VOID(CATEGORY, FUNC, PARAMS)
Append a string to an object description, escaping invalid UTF-8.
Edit distance calculation algorithm.
Hierarchy of classes which Xapian can throw as exceptions.
Return docs containing terms forming a particular exact phrase.
Return document ids from an external source.
C++ STL heap implementation with extensions.
N-way OR postlist with wt=max(wt_i)
void pop(_RandomAccessIterator first, _RandomAccessIterator last, _Compare comp)
void replace(_RandomAccessIterator first, _RandomAccessIterator last, _Compare comp)
void make(_RandomAccessIterator first, _RandomAccessIterator last, _Compare comp)
void sort(_RandomAccessIterator first, _RandomAccessIterator last, _Compare comp)
string str(int value)
Convert int to std::string.
static double string_frac(const string &s, size_t prefix)
static T estimate_and_not(T l, T r, U n)
static Xapian::doccount estimate_range_freq(const string &lo, const string &hi, const string &begin, const string *end, Xapian::doccount value_freq)
The Xapian namespace contains public interfaces for the Xapian library.
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
unsigned valueno
The number for a value slot in a document.
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Return docs containing terms within a specified window.
Various assertion macros.
#define AssertRel(A, REL, B)
Wrapper postlist providing positions for an OR.
PostList class implementing Query::OP_OR.
void unpack_throw_serialisation_error(const char *p)
Throw appropriate SerialisationError.
Pack types into strings and unpack them again.
bool unpack_string(const char **p, const char *end, std::string &result)
Decode a std::string from a string.
bool unpack_uint(const char **p, const char *end, U *result)
Decode an unsigned integer from a string.
void pack_uint(std::string &s, U value)
Append an encoded unsigned integer to a string.
void pack_string(std::string &s, std::string_view value)
Append an encoded std::string to a string.
void pack_string_empty(std::string &s)
Append an empty encoded std::string to a string.
Return docs containing terms forming a particular phrase.
External sources of posting information.
Abstract base class for postlists.
static constexpr unsigned MAX_UTF_8_CHARACTER_LENGTH
Details passed around while building PostList tree from Query tree.
string serialise_double(double v)
Serialise a double to a string.
double unserialise_double(const char **p, const char *end)
Unserialise a double serialised by serialise_double.
functions to serialise and unserialise a double
Convert types to std::string.
Various handy string-related helpers.
bool endswith(std::string_view s, char sfx)
bool startswith(std::string_view s, char pfx)
Class providing an operator which sorts postlists to select max or terms.
bool operator()(PostList *a, PostList *b)
Return true if and only if a has a strictly greater termweight than b.
Comparison functor which orders by descending termfreq.
bool operator()(const PostList *a, const PostList *b) const
Order PostList* by descending get_termfreq().
The frequencies for a term.
Xapian::doccount reltermfreq
Xapian::doccount termfreq
Xapian::termcount collfreq
Abstract base class for termlists.
Unicode and UTF-8 related classes and functions.
void description_append(std::string &desc, std::string_view s)
Return document ids matching a >= test on a specified doc value.
Return document ids matching a range test on a specified doc value.