Add support for "issub" special field specifying that the results should be standalone (issub:0) or embedded (issub:1)

This commit is contained in:
Jean-Francois Dockes
2021-04-24 13:48:16 +02:00
parent d1058dc676
commit e5c320ca51
8 changed files with 107 additions and 61 deletions
+2 -2
View File
@@ -2557,7 +2557,7 @@ bool Db::getSubDocs(const Doc &idoc, vector<Doc>& subdocs)
LOGERR("Db::getSubDocs: xapian error: " << m_reason << "\n");
return false;
}
if (xit == xdoc.termlist_end()) {
if (xit == xdoc.termlist_end() || get_prefix(*xit) != parent_prefix) {
LOGERR("Db::getSubDocs: parent term not found\n");
return false;
}
@@ -2642,7 +2642,7 @@ bool Db::getContainerDoc(const Doc &idoc, Doc& ctdoc)
LOGERR("Db::getContainerDoc: xapian error: " << m_reason << "\n");
return false;
}
if (xit == xdoc.termlist_end()) {
if (xit == xdoc.termlist_end() || get_prefix(*xit) != parent_prefix) {
LOGERR("Db::getContainerDoc: parent term not found\n");
return false;
}
+14
View File
@@ -151,6 +151,20 @@ inline string strip_prefix(const string& trm)
return trm.substr(st);
}
inline string get_prefix(const string& trm)
{
if (!has_prefix(trm))
return trm;
string::size_type st = 0;
if (o_index_stripchars) {
st = trm.find_first_not_of("ABCDEFIJKLMNOPQRSTUVWXYZ");
return trm.substr(0, st);
} else {
st = trm.find_last_of(":") + 1;
return trm.substr(1, st-2);
}
}
inline string wrap_prefix(const string& pfx)
{
if (o_index_stripchars) {
+32 -7
View File
@@ -152,8 +152,7 @@ private:
};
Query::Query(Db *db)
: m_nq(new Native(this)), m_db(db), m_sorter(0), m_sortAscending(true),
m_collapseDuplicates(false), m_resCnt(-1), m_snipMaxPosWalk(1000000)
: m_nq(new Native(this)), m_db(db)
{
if (db)
db->getConf()->getConfParam("snippetMaxPosWalk", &m_snipMaxPosWalk);
@@ -179,6 +178,27 @@ void Query::setSortBy(const string& fld, bool ascending) {
(m_sortAscending ? "ascending" : "descending") << "\n");
}
static const string parent_prefix{"F"};
class SubdocDecider : public Xapian::MatchDecider {
public:
SubdocDecider(bool sel) : MatchDecider(), m_select(sel) {}
virtual ~SubdocDecider() {}
virtual bool operator()(const Xapian::Document &doc) const {
bool hasparent{false};
try {
Xapian::TermIterator xit = doc.termlist_begin();
xit.skip_to(wrap_prefix(parent_prefix));
hasparent = (xit != doc.termlist_end()) && (get_prefix(*xit) == parent_prefix);
} catch (...) {
}
return hasparent == m_select;
}
bool m_select;
};
// Prepare query out of user search data
bool Query::setQuery(std::shared_ptr<SearchData> sdata)
{
@@ -199,8 +219,13 @@ bool Query::setQuery(std::shared_ptr<SearchData> sdata)
m_reason += sdata->getReason();
return false;
}
m_nq->xquery = xq;
if (sdata->getSubSpec() == SearchData::SUBDOC_NO) {
m_nq->subdecider = new SubdocDecider(false);
} else if (sdata->getSubSpec() == SearchData::SUBDOC_YES) {
m_nq->subdecider = new SubdocDecider(true);
}
string d;
for (int tries = 0; tries < 2; tries++) {
@@ -361,7 +386,8 @@ int Query::getResCnt(int checkatleast, bool useestimate)
Chrono chron;
XAPTRY(if (checkatleast == -1)
checkatleast = m_db->docCnt();
m_nq->xmset = m_nq->xenquire->get_mset(0, qquantum, checkatleast),
m_nq->xmset = m_nq->xenquire->get_mset(
0, qquantum, checkatleast, 0, m_nq->subdecider),
m_db->m_ndb->xrdb, m_reason);
if (!m_reason.empty()) {
LOGERR("xenquire->get_mset: exception: " << m_reason << "\n");
@@ -401,10 +427,9 @@ bool Query::getDoc(int xapi, Doc &doc, bool fetchtext)
if (!(xapi >= first && xapi <= last)) {
LOGDEB("Fetching for first " << xapi << ", count " << qquantum << "\n");
XAPTRY(m_nq->xmset = m_nq->xenquire->get_mset(xapi, qquantum,
(const Xapian::RSet *)0),
XAPTRY(m_nq->xmset = m_nq->xenquire->get_mset(
xapi, qquantum, nullptr, m_nq->subdecider),
m_db->m_ndb->xrdb, m_reason);
if (!m_reason.empty()) {
LOGERR("enquire->get_mset: exception: " << m_reason << "\n");
return false;
+5 -5
View File
@@ -139,13 +139,13 @@ public:
private:
std::string m_reason; // Error explanation
Db *m_db;
void *m_sorter;
void *m_sorter{nullptr};
std::string m_sortField;
bool m_sortAscending;
bool m_collapseDuplicates;
int m_resCnt;
bool m_sortAscending{true};
bool m_collapseDuplicates{false};
int m_resCnt{-1};
std::shared_ptr<SearchData> m_sd;
int m_snipMaxPosWalk;
int m_snipMaxPosWalk{1000000};
};
#ifndef NO_NAMESPACES
+7 -5
View File
@@ -32,24 +32,26 @@ namespace Rcl {
class Query::Native {
public:
// The query I belong to
Query *m_q;
Query *m_q{nullptr};
// query descriptor: terms and subqueries joined by operators
// (or/and etc...)
Xapian::Query xquery;
// Open query descriptor.
Xapian::Enquire *xenquire;
Xapian::Enquire *xenquire{nullptr};
// Partial result set
Xapian::MSet xmset;
// Term frequencies for current query. See makeAbstract, setQuery
std::map<std::string, double> termfreqs;
Xapian::MatchDecider *subdecider{nullptr};
Native(Query *q)
: m_q(q), xenquire(0) { }
: m_q(q), xenquire(0) {}
~Native() {
clear();
}
void clear() {
delete xenquire; xenquire = 0;
deleteZ(xenquire);
deleteZ(subdecider);
termfreqs.clear();
}
/** Return a list of terms which matched for a specific result document */
+15 -2
View File
@@ -114,6 +114,17 @@ public:
void setMinSize(int64_t size) {m_minSize = size;}
void setMaxSize(int64_t size) {m_maxSize = size;}
enum SubdocSpec {SUBDOC_ANY = -1, SUBDOC_NO = 0, SUBDOC_YES = 1};
void setSubSpec(int spec) {
switch (spec) {
case SUBDOC_ANY:
case SUBDOC_NO:
case SUBDOC_YES:
m_subspec = spec;
}
}
int getSubSpec() {return m_subspec;}
/** Set date span for filtering results */
void setDateSpan(DateInterval *dip) {m_dates = *dip; m_haveDates = true;}
@@ -174,12 +185,14 @@ private:
std::shared_ptr<SearchDataClauseDist> m_autophrase;
// Special stuff produced by input which looks like a clause but means
// something else (date and size specs)
// something else (date, size specs, etc.)
bool m_haveDates{false};
DateInterval m_dates; // Restrict to date interval
int64_t m_maxSize{-1};
int64_t m_minSize{-1};
// Filtering for subdocs: -1:any, 0: only free-standing, 1: only subdocs
int m_subspec{SUBDOC_ANY};
// Printable expanded version of the complete query, retrieved/set
// from rcldb after the Xapian::setQuery() call
std::string m_description;