mirror of https://github.com/djcb/mu.git
query: fix include-related.
mu-query.cc: - make_related_enquire: don't include first query in qvec, we already have all thread IDs we need to query in thread_ds. - run_related: always sort first query by date, explained by the comment. - run_related: include qflags (in particular ascending vs descending) in leader_qflags. - run_theaded: don't limit results to maxnum, that results in threads potentially being cut off. mu-server.cc: - output_sexp: don't limit results to maxnum so as to match the behaviour of mu find (and avoid cuttong off threads). Fixes #1924 and #1911.
This commit is contained in:
parent
40b5b89775
commit
ee4bf5664a
|
@ -45,12 +45,11 @@ struct Query::Private {
|
||||||
|
|
||||||
Xapian::Enquire make_enquire (const std::string& expr,
|
Xapian::Enquire make_enquire (const std::string& expr,
|
||||||
MuMsgFieldId sortfieldid, QueryFlags qflags) const;
|
MuMsgFieldId sortfieldid, QueryFlags qflags) const;
|
||||||
Xapian::Enquire make_related_enquire (const Xapian::Query& first_q,
|
Xapian::Enquire make_related_enquire (const StringSet& thread_ids,
|
||||||
const StringSet& thread_ids,
|
|
||||||
MuMsgFieldId sortfieldid, QueryFlags qflags) const;
|
MuMsgFieldId sortfieldid, QueryFlags qflags) const;
|
||||||
|
|
||||||
Option<QueryResults> run_threaded (QueryResults&& qres, Xapian::Enquire& enq,
|
Option<QueryResults> run_threaded (QueryResults&& qres, Xapian::Enquire& enq,
|
||||||
QueryFlags qflags, size_t max_size) const;
|
QueryFlags qflags) const;
|
||||||
Option<QueryResults> run_singular (const std::string& expr, MuMsgFieldId sortfieldid,
|
Option<QueryResults> run_singular (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||||
QueryFlags qflags, size_t maxnum) const;
|
QueryFlags qflags, size_t maxnum) const;
|
||||||
Option<QueryResults> run_related (const std::string& expr, MuMsgFieldId sortfieldid,
|
Option<QueryResults> run_related (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||||
|
@ -101,14 +100,13 @@ Query::Private::make_enquire (const std::string& expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
Xapian::Enquire
|
Xapian::Enquire
|
||||||
Query::Private::make_related_enquire (const Xapian::Query& first_q,
|
Query::Private::make_related_enquire (const StringSet& thread_ids,
|
||||||
const StringSet& thread_ids,
|
|
||||||
MuMsgFieldId sortfieldid, QueryFlags qflags) const
|
MuMsgFieldId sortfieldid, QueryFlags qflags) const
|
||||||
{
|
{
|
||||||
Xapian::Enquire enq{store_.database()};
|
Xapian::Enquire enq{store_.database()};
|
||||||
static std::string pfx (1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_THREAD_ID));
|
static std::string pfx (1, mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_THREAD_ID));
|
||||||
|
|
||||||
std::vector<Xapian::Query> qvec{first_q};
|
std::vector<Xapian::Query> qvec;
|
||||||
for (auto&& t: thread_ids)
|
for (auto&& t: thread_ids)
|
||||||
qvec.emplace_back(pfx + t);
|
qvec.emplace_back(pfx + t);
|
||||||
Xapian::Query qr{Xapian::Query::OP_OR, qvec.begin(), qvec.end()};
|
Xapian::Query qr{Xapian::Query::OP_OR, qvec.begin(), qvec.end()};
|
||||||
|
@ -129,7 +127,7 @@ struct ThreadKeyMaker: public Xapian::KeyMaker {
|
||||||
|
|
||||||
Option<QueryResults>
|
Option<QueryResults>
|
||||||
Query::Private::run_threaded (QueryResults&& qres, Xapian::Enquire& enq,
|
Query::Private::run_threaded (QueryResults&& qres, Xapian::Enquire& enq,
|
||||||
QueryFlags qflags, size_t max_size) const
|
QueryFlags qflags) const
|
||||||
{
|
{
|
||||||
const auto descending{any_of(qflags & QueryFlags::Descending)};
|
const auto descending{any_of(qflags & QueryFlags::Descending)};
|
||||||
|
|
||||||
|
@ -140,7 +138,7 @@ Query::Private::run_threaded (QueryResults&& qres, Xapian::Enquire& enq,
|
||||||
|
|
||||||
DeciderInfo minfo;
|
DeciderInfo minfo;
|
||||||
minfo.matches = qres.query_matches();
|
minfo.matches = qres.query_matches();
|
||||||
auto mset{enq.get_mset(0, max_size, {},
|
auto mset{enq.get_mset(0, store_.size(), {},
|
||||||
make_thread_decider(qflags, minfo).get())};
|
make_thread_decider(qflags, minfo).get())};
|
||||||
mset.fetch();
|
mset.fetch();
|
||||||
|
|
||||||
|
@ -172,7 +170,7 @@ Query::Private::run_singular (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||||
|
|
||||||
auto qres{QueryResults{mset, std::move(minfo.matches)}};
|
auto qres{QueryResults{mset, std::move(minfo.matches)}};
|
||||||
|
|
||||||
return threading ? run_threaded(std::move(qres), enq, qflags, maxnum) : qres;
|
return threading ? run_threaded(std::move(qres), enq, qflags) : qres;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Option<std::string>
|
static Option<std::string>
|
||||||
|
@ -192,12 +190,12 @@ Query::Private::run_related (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||||
// moreover, in either threaded or non-threaded case, we sort the first
|
// moreover, in either threaded or non-threaded case, we sort the first
|
||||||
// ("leader") query by date, i.e, we prefer the newest or oldest
|
// ("leader") query by date, i.e, we prefer the newest or oldest
|
||||||
// (descending) messages.
|
// (descending) messages.
|
||||||
const auto leader_qflags{QueryFlags::Leader};
|
const auto leader_qflags{QueryFlags::Leader | qflags};
|
||||||
const auto threading{any_of(qflags & QueryFlags::Threading)};
|
const auto threading{any_of(qflags & QueryFlags::Threading)};
|
||||||
|
|
||||||
// Run our first, "leader" query
|
// Run our first, "leader" query
|
||||||
DeciderInfo minfo{};
|
DeciderInfo minfo{};
|
||||||
auto enq{make_enquire(expr, sortfieldid, leader_qflags)};
|
auto enq{make_enquire(expr, MU_MSG_FIELD_ID_DATE, leader_qflags)};
|
||||||
const auto mset{enq.get_mset(0, maxnum, {},
|
const auto mset{enq.get_mset(0, maxnum, {},
|
||||||
make_leader_decider(leader_qflags, minfo).get())};
|
make_leader_decider(leader_qflags, minfo).get())};
|
||||||
|
|
||||||
|
@ -214,13 +212,12 @@ Query::Private::run_related (const std::string& expr, MuMsgFieldId sortfieldid,
|
||||||
// In the threaded-case, we search among _all_ messages, since complete
|
// In the threaded-case, we search among _all_ messages, since complete
|
||||||
// threads are preferred; no need to sort in that case since the search
|
// threads are preferred; no need to sort in that case since the search
|
||||||
// is unlimited and the sorting happens during threading.
|
// is unlimited and the sorting happens during threading.
|
||||||
auto r_enq{make_related_enquire(enq.get_query(), minfo.thread_ids,
|
auto r_enq{make_related_enquire(minfo.thread_ids,
|
||||||
threading ? MU_MSG_FIELD_ID_NONE : sortfieldid, qflags)};
|
threading ? MU_MSG_FIELD_ID_NONE : sortfieldid, qflags)};
|
||||||
const auto r_mset{r_enq.get_mset(0, threading ? store_.size() : maxnum,
|
const auto r_mset{r_enq.get_mset(0, threading ? store_.size() : maxnum,
|
||||||
{}, make_related_decider(qflags, minfo).get())};
|
{}, make_related_decider(qflags, minfo).get())};
|
||||||
auto qres{QueryResults{r_mset, std::move(minfo.matches)}};
|
auto qres{QueryResults{r_mset, std::move(minfo.matches)}};
|
||||||
|
return threading ? run_threaded(std::move(qres), r_enq, qflags) : qres;
|
||||||
return threading ? run_threaded(std::move(qres), r_enq, qflags, maxnum) : qres;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ struct Server::Private {
|
||||||
void output_sexp(Sexp::List&& lst) const {
|
void output_sexp(Sexp::List&& lst) const {
|
||||||
output_sexp(Sexp::make_list(std::move(lst)));
|
output_sexp(Sexp::make_list(std::move(lst)));
|
||||||
}
|
}
|
||||||
size_t output_sexp (const QueryResults& qres, unsigned maxnum);
|
size_t output_sexp (const QueryResults& qres);
|
||||||
|
|
||||||
//
|
//
|
||||||
// handlers for various commands.
|
// handlers for various commands.
|
||||||
|
@ -731,13 +731,10 @@ determine_docids (const Query& q, const Parameters& params)
|
||||||
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
Server::Private::output_sexp (const QueryResults& qres, unsigned maxnum)
|
Server::Private::output_sexp (const QueryResults& qres)
|
||||||
{
|
{
|
||||||
size_t n{};
|
size_t n{};
|
||||||
for (auto&& mi: qres) {
|
for (auto&& mi: qres) {
|
||||||
|
|
||||||
if (n >= maxnum)
|
|
||||||
break;
|
|
||||||
++n;
|
++n;
|
||||||
auto msg{mi.floating_msg()};
|
auto msg{mi.floating_msg()};
|
||||||
if (!msg)
|
if (!msg)
|
||||||
|
@ -745,7 +742,7 @@ Server::Private::output_sexp (const QueryResults& qres, unsigned maxnum)
|
||||||
|
|
||||||
auto qm{mi.query_match()};
|
auto qm{mi.query_match()};
|
||||||
output_sexp(build_message_sexp(msg, mi.doc_id(),
|
output_sexp(build_message_sexp(msg, mi.doc_id(),
|
||||||
qm, MU_MSG_OPTION_HEADERS_ONLY));
|
qm, MU_MSG_OPTION_HEADERS_ONLY));
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
|
@ -796,7 +793,7 @@ Server::Private::find_handler (const Parameters& params)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto foundnum{output_sexp (*qres, maxnum)};
|
const auto foundnum{output_sexp (*qres)};
|
||||||
Sexp::List lst;
|
Sexp::List lst;
|
||||||
lst.add_prop(":found", Sexp::make_number(foundnum));
|
lst.add_prop(":found", Sexp::make_number(foundnum));
|
||||||
output_sexp(std::move(lst));
|
output_sexp(std::move(lst));
|
||||||
|
|
Loading…
Reference in New Issue