00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include "omdebug.h"
00026
00027 #include <xapian/document.h>
00028 #include <xapian/enquire.h>
00029 #include <xapian/error.h>
00030 #include <xapian/errorhandler.h>
00031 #include <xapian/expanddecider.h>
00032 #include <xapian/termiterator.h>
00033
00034 #include "vectortermlist.h"
00035
00036 #include "rset.h"
00037 #include "multimatch.h"
00038 #include "expand.h"
00039 #include "database.h"
00040 #include "omenquireinternal.h"
00041 #include "stats.h"
00042 #include "utils.h"
00043
00044 #include <vector>
00045 #include "autoptr.h"
00046 #include <algorithm>
00047 #include <cfloat>
00048 #include <math.h>
00049
00050 using namespace std;
00051
00052 namespace Xapian {
00053
00054 MatchDecider::~MatchDecider() { }
00055
00056
00057
00058 RSet::RSet() : internal(new RSet::Internal())
00059 {
00060 }
00061
00062 RSet::RSet(const RSet &other) : internal(other.internal)
00063 {
00064 }
00065
00066 void
00067 RSet::operator=(const RSet &other)
00068 {
00069 internal = other.internal;
00070 }
00071
00072 RSet::~RSet()
00073 {
00074 }
00075
00076 Xapian::doccount
00077 RSet::size() const
00078 {
00079 return internal->items.size();
00080 }
00081
00082 bool
00083 RSet::empty() const
00084 {
00085 return internal->items.empty();
00086 }
00087
00088 void
00089 RSet::add_document(Xapian::docid did)
00090 {
00091 internal->items.insert(did);
00092 }
00093
00094 void
00095 RSet::remove_document(Xapian::docid did)
00096 {
00097 internal->items.erase(did);
00098 }
00099
00100 bool
00101 RSet::contains(Xapian::docid did) const
00102 {
00103 return internal->items.find(did) != internal->items.end();
00104 }
00105
00106 string
00107 RSet::get_description() const
00108 {
00109 return "RSet(" + internal->get_description() + ")";
00110 }
00111
00112 string
00113 RSet::Internal::get_description() const
00114 {
00115 string description("RSet::Internal(");
00116
00117 set<Xapian::docid>::const_iterator i;
00118 for (i = items.begin(); i != items.end(); ++i) {
00119 if (i != items.begin()) description += ", ";
00120 description += om_tostring(*i);
00121 }
00122
00123 description += ')';
00124
00125 return description;
00126 }
00127
00128 namespace Internal {
00129
00130
00131
00132 string
00133 MSetItem::get_description() const
00134 {
00135 string description;
00136
00137 description = om_tostring(did) + ", " + om_tostring(wt) + ", " +
00138 collapse_key;
00139
00140 description = "Xapian::MSetItem(" + description + ")";
00141
00142 return description;
00143 }
00144
00145 }
00146
00147
00148
00149 MSet::MSet() : internal(new MSet::Internal())
00150 {
00151 }
00152
00153 MSet::MSet(MSet::Internal * internal_) : internal(internal_)
00154 {
00155 }
00156
00157 MSet::~MSet()
00158 {
00159 }
00160
00161 MSet::MSet(const MSet & other) : internal(other.internal)
00162 {
00163 }
00164
00165 void
00166 MSet::operator=(const MSet &other)
00167 {
00168 internal = other.internal;
00169 }
00170
00171 void
00172 MSet::fetch(const MSetIterator & beginiter, const MSetIterator & enditer) const
00173 {
00174 DEBUGAPICALL(void, "Xapian::MSet::fetch", beginiter << ", " << enditer);
00175 Assert(internal.get() != 0);
00176 if (beginiter != enditer)
00177 internal->fetch_items(beginiter.index, enditer.index - 1);
00178 }
00179
00180 void
00181 MSet::fetch(const MSetIterator & beginiter) const
00182 {
00183 DEBUGAPICALL(void, "Xapian::MSet::fetch", beginiter);
00184 Assert(internal.get() != 0);
00185 internal->fetch_items(beginiter.index, beginiter.index);
00186 }
00187
00188 void
00189 MSet::fetch() const
00190 {
00191 DEBUGAPICALL(void, "Xapian::MSet::fetch", "");
00192 Assert(internal.get() != 0);
00193 if (!internal->items.empty())
00194 internal->fetch_items(0, internal->items.size() - 1);
00195 }
00196
00197 percent
00198 MSet::convert_to_percent(Xapian::weight wt) const
00199 {
00200 DEBUGAPICALL(Xapian::percent, "Xapian::MSet::convert_to_percent", wt);
00201 Assert(internal.get() != 0);
00202 RETURN(internal->convert_to_percent_internal(wt));
00203 }
00204
00205 percent
00206 MSet::convert_to_percent(const MSetIterator & it) const
00207 {
00208 DEBUGAPICALL(Xapian::percent, "Xapian::MSet::convert_to_percent", it);
00209 Assert(internal.get() != 0);
00210 RETURN(internal->convert_to_percent_internal(it.get_weight()));
00211 }
00212
00213 Xapian::doccount
00214 MSet::get_termfreq(const string &tname) const
00215 {
00216 DEBUGAPICALL(Xapian::doccount, "Xapian::MSet::get_termfreq", tname);
00217 map<string, Internal::TermFreqAndWeight>::const_iterator i;
00218 Assert(internal.get() != 0);
00219 i = internal->termfreqandwts.find(tname);
00220 if (i == internal->termfreqandwts.end()) {
00221 throw InvalidArgumentError("Term frequency of `" + tname +
00222 "' not available.");
00223 }
00224 RETURN(i->second.termfreq);
00225 }
00226
00227 Xapian::weight
00228 MSet::get_termweight(const string &tname) const
00229 {
00230 DEBUGAPICALL(Xapian::weight, "Xapian::MSet::get_termweight", tname);
00231 map<string, Internal::TermFreqAndWeight>::const_iterator i;
00232 Assert(internal.get() != 0);
00233 i = internal->termfreqandwts.find(tname);
00234 if (i == internal->termfreqandwts.end()) {
00235 throw InvalidArgumentError("Term weight of `" + tname +
00236 "' not available.");
00237 }
00238 RETURN(i->second.termweight);
00239 }
00240
00241 Xapian::doccount
00242 MSet::get_firstitem() const
00243 {
00244 Assert(internal.get() != 0);
00245 return internal->firstitem;
00246 }
00247
00248 Xapian::doccount
00249 MSet::get_matches_lower_bound() const
00250 {
00251 Assert(internal.get() != 0);
00252 return internal->matches_lower_bound;
00253 }
00254
00255 Xapian::doccount
00256 MSet::get_matches_estimated() const
00257 {
00258 Assert(internal.get() != 0);
00259 return internal->matches_estimated;
00260 }
00261
00262 Xapian::doccount
00263 MSet::get_matches_upper_bound() const
00264 {
00265 Assert(internal.get() != 0);
00266 return internal->matches_upper_bound;
00267 }
00268
00269 Xapian::weight
00270 MSet::get_max_possible() const
00271 {
00272 Assert(internal.get() != 0);
00273 return internal->max_possible;
00274 }
00275
00276 Xapian::weight
00277 MSet::get_max_attained() const
00278 {
00279 Assert(internal.get() != 0);
00280 return internal->max_attained;
00281 }
00282
00283 Xapian::doccount
00284 MSet::size() const
00285 {
00286 Assert(internal.get() != 0);
00287 return internal->items.size();
00288 }
00289
00290 bool
00291 MSet::empty() const
00292 {
00293 Assert(internal.get() != 0);
00294 return internal->items.empty();
00295 }
00296
00297 void
00298 MSet::swap(MSet & other)
00299 {
00300 std::swap(internal, other.internal);
00301 }
00302
00303 MSetIterator
00304 MSet::begin() const
00305 {
00306 return MSetIterator(0, *this);
00307 }
00308
00309 MSetIterator
00310 MSet::end() const
00311 {
00312 Assert(internal.get() != 0);
00313 return MSetIterator(internal->items.size(), *this);
00314 }
00315
00316 MSetIterator
00317 MSet::operator[](Xapian::doccount i) const
00318 {
00319
00320 Assert(0 < (i + 1) && i < size());
00321 return MSetIterator(i, *this);
00322 }
00323
00324 MSetIterator
00325 MSet::back() const
00326 {
00327 Assert(!empty());
00328 Assert(internal.get() != 0);
00329 return MSetIterator(internal->items.size() - 1, *this);
00330 }
00331
00332 string
00333 MSet::get_description() const
00334 {
00335 Assert(internal.get() != 0);
00336 return "Xapian::MSet(" + internal->get_description() + ")";
00337 }
00338
00339 percent
00340 MSet::Internal::convert_to_percent_internal(Xapian::weight wt) const
00341 {
00342 DEBUGAPICALL(Xapian::percent, "Xapian::MSet::Internal::convert_to_percent_internal", wt);
00343 if (percent_factor == 0) RETURN(100);
00344
00345
00346 double v = wt * percent_factor + 100.0 * DBL_EPSILON;
00347 Xapian::percent pcent = static_cast<Xapian::percent>(v);
00348 DEBUGLINE(API, "wt = " << wt << ", max_possible = "
00349 << max_possible << " => pcent = " << pcent);
00350 if (pcent > 100) pcent = 100;
00351 if (pcent < 0) pcent = 0;
00352 if (pcent == 0 && wt > 0) pcent = 1;
00353
00354 RETURN(pcent);
00355 }
00356
00357 Document
00358 MSet::Internal::get_doc_by_index(Xapian::doccount index) const
00359 {
00360 DEBUGCALL(API, Document, "Xapian::MSet::Internal::Data::get_doc_by_index",
00361 index);
00362 index += firstitem;
00363 map<Xapian::doccount, Document>::const_iterator doc;
00364 doc = indexeddocs.find(index);
00365 if (doc != indexeddocs.end()) {
00366 RETURN(doc->second);
00367 }
00368 if (index < firstitem || index >= firstitem + items.size()) {
00369 throw RangeError("The mset returned from the match does not contain the document at index " + om_tostring(index));
00370 }
00371 fetch_items(index, index);
00372
00373 read_docs();
00374 Assert(indexeddocs.find(index) != indexeddocs.end());
00375 Assert(indexeddocs.find(index)->first == index);
00376 RETURN(indexeddocs.find(index)->second);
00377 }
00378
00379 void
00380 MSet::Internal::fetch_items(Xapian::doccount first, Xapian::doccount last) const
00381 {
00382 DEBUGAPICALL(void, "Xapian::MSet::Internal::Data::fetch_items",
00383 first << ", " << last);
00384 if (enquire.get() == 0) {
00385 throw InvalidOperationError("Can't fetch documents from an MSet which is not derived from a query.");
00386 }
00387 for (Xapian::doccount i = first; i <= last; ++i) {
00388 map<Xapian::doccount, Document>::const_iterator doc;
00389 doc = indexeddocs.find(i);
00390 if (doc == indexeddocs.end()) {
00391
00392 set<Xapian::doccount>::const_iterator s;
00393 s = requested_docs.find(i);
00394 if (s == requested_docs.end()) {
00395
00396 enquire->request_doc(items[i - firstitem]);
00397 requested_docs.insert(i);
00398 }
00399 }
00400 }
00401 }
00402
00403 string
00404 MSet::Internal::get_description() const
00405 {
00406 string description = "Xapian::MSet::Internal(";
00407
00408 description += "firstitem=" + om_tostring(firstitem) + ", " +
00409 "matches_lower_bound=" + om_tostring(matches_lower_bound) + ", " +
00410 "matches_estimated=" + om_tostring(matches_estimated) + ", " +
00411 "matches_upper_bound=" + om_tostring(matches_upper_bound) + ", " +
00412 "max_possible=" + om_tostring(max_possible) + ", " +
00413 "max_attained=" + om_tostring(max_attained);
00414
00415 for (vector<Xapian::Internal::MSetItem>::const_iterator i = items.begin();
00416 i != items.end(); ++i) {
00417 if (!description.empty()) description += ", ";
00418 description += i->get_description();
00419 }
00420
00421 description += ")";
00422
00423 return description;
00424 }
00425
00426 void
00427 MSet::Internal::read_docs() const
00428 {
00429 set<Xapian::doccount>::const_iterator i;
00430 for (i = requested_docs.begin(); i != requested_docs.end(); ++i) {
00431 indexeddocs[*i] = enquire->read_doc(items[*i - firstitem]);
00432 DEBUGLINE(API, "stored doc at index " << *i << " is " << indexeddocs[*i]);
00433 }
00434
00435 requested_docs.clear();
00436 }
00437
00438
00439
00440 string
00441 Xapian::Internal::ESetItem::get_description() const
00442 {
00443 return "Xapian::Internal::ESetItem(" + tname + ", " + om_tostring(wt) + ")";
00444 }
00445
00446
00447
00448 ESet::ESet() : internal(new Internal()) { }
00449
00450 ESet::~ESet()
00451 {
00452 }
00453
00454 ESet::ESet(const ESet & other) : internal(other.internal)
00455 {
00456 }
00457
00458 void
00459 ESet::operator=(const ESet &other)
00460 {
00461 internal = other.internal;
00462 }
00463
00464 Xapian::termcount
00465 ESet::get_ebound() const
00466 {
00467 return internal->ebound;
00468 }
00469
00470 Xapian::termcount
00471 ESet::size() const
00472 {
00473 return internal->items.size();
00474 }
00475
00476 bool
00477 ESet::empty() const
00478 {
00479 return internal->items.empty();
00480 }
00481
00482 void
00483 ESet::swap(ESet & other)
00484 {
00485 std::swap(internal, other.internal);
00486 }
00487
00488 ESetIterator
00489 ESet::begin() const
00490 {
00491 return ESetIterator(0, *this);
00492 }
00493
00494 ESetIterator
00495 ESet::end() const
00496 {
00497 Assert(internal.get() != 0);
00498 return ESetIterator(internal->items.size(), *this);
00499 }
00500
00501 ESetIterator
00502 ESet::operator[](Xapian::termcount i) const
00503 {
00504
00505 Assert(0 < (i + 1) && i < size());
00506 return ESetIterator(i, *this);
00507 }
00508
00509 ESetIterator
00510 ESet::back() const
00511 {
00512 Assert(!empty());
00513 Assert(internal.get() != 0);
00514 return ESetIterator(internal->items.size() - 1, *this);
00515 }
00516
00517 string
00518 ESet::get_description() const
00519 {
00520 Assert(internal.get() != 0);
00521 return "Xapian::ESet(" + internal->get_description() + ")";
00522 }
00523
00525
00527
00528 string
00529 Xapian::ESet::Internal::get_description() const
00530 {
00531 string description = "ebound=" + om_tostring(ebound);
00532
00533 for (vector<Xapian::Internal::ESetItem>::const_iterator i = items.begin();
00534 i != items.end();
00535 i++) {
00536 description += ", " + i->get_description();
00537 }
00538
00539 return "Xapian::ESet::Internal(" + description + ")";
00540 }
00541
00542
00543
00544 const string &
00545 ESetIterator::operator *() const
00546 {
00547 return eset.internal->items[index].tname;
00548 }
00549
00550 Xapian::weight
00551 ESetIterator::get_weight() const
00552 {
00553 return eset.internal->items[index].wt;
00554 }
00555
00556 string
00557 ESetIterator::get_description() const
00558 {
00559 return "Xapian::ESetIterator(" + om_tostring(index) + ")";
00560 }
00561
00562
00563
00564 Xapian::docid
00565 MSetIterator::operator *() const
00566 {
00567 return mset.internal->items[index].did;
00568 }
00569
00570 Document
00571 MSetIterator::get_document() const
00572 {
00573 return mset.internal->get_doc_by_index(index);
00574 }
00575
00576 Xapian::weight
00577 MSetIterator::get_weight() const
00578 {
00579 return mset.internal->items[index].wt;
00580 }
00581
00582 std::string
00583 MSetIterator::get_collapse_key() const
00584 {
00585 return mset.internal->items[index].collapse_key;
00586 }
00587
00588 Xapian::doccount
00589 MSetIterator::get_collapse_count() const
00590 {
00591 return mset.internal->items[index].collapse_count;
00592 }
00593
00594 Xapian::percent
00595 MSetIterator::get_percent() const
00596 {
00597 DEBUGAPICALL(Xapian::percent, "MSetIterator::get_percent", "");
00598 RETURN(mset.internal->convert_to_percent_internal(get_weight()));
00599 }
00600
00601 string
00602 MSetIterator::get_description() const
00603 {
00604 return "Xapian::MSetIterator(" + om_tostring(index) + ")";
00605 }
00606
00607
00608
00609 Enquire::Internal::Internal(const Database &db_, ErrorHandler * errorhandler_)
00610 : db(db_), query(), collapse_key(Xapian::BAD_VALUENO),
00611 order(Enquire::ASCENDING), percent_cutoff(0), weight_cutoff(0),
00612 sort_key(Xapian::BAD_VALUENO), sort_by(REL), sort_value_forward(true),
00613 sorter(0), errorhandler(errorhandler_), weight(0)
00614 {
00615 if (db.internal.empty()) {
00616 throw InvalidArgumentError("Can't make an Enquire object from an uninitialised Database object.");
00617 }
00618 }
00619
00620 Enquire::Internal::~Internal()
00621 {
00622 delete weight;
00623 weight = 0;
00624 }
00625
00626 void
00627 Enquire::Internal::set_query(const Query &query_, termcount qlen_)
00628 {
00629 query = query_;
00630 qlen = qlen_ ? qlen_ : query.get_length();
00631 }
00632
00633 const Query &
00634 Enquire::Internal::get_query()
00635 {
00636 return query;
00637 }
00638
00639 MSet
00640 Enquire::Internal::get_mset(Xapian::doccount first, Xapian::doccount maxitems,
00641 Xapian::doccount check_at_least, const RSet *rset,
00642 const MatchDecider *mdecider,
00643 const MatchDecider *matchspy) const
00644 {
00645 DEBUGCALL(API, MSet, "Enquire::Internal::get_mset", first << ", " <<
00646 maxitems << ", " << check_at_least << ", " << rset << ", " <<
00647 mdecider << ", " << matchspy);
00648
00649 if (weight == 0) {
00650 weight = new BM25Weight;
00651 }
00652
00653 Stats stats;
00654 ::MultiMatch match(db, query.internal.get(), qlen, rset, collapse_key,
00655 percent_cutoff, weight_cutoff,
00656 order, sort_key, sort_by, sort_value_forward, sorter,
00657 errorhandler, stats, weight);
00658
00659 MSet retval;
00660 match.get_mset(first, maxitems, check_at_least, retval,
00661 stats, mdecider, matchspy);
00662
00663 Assert(weight->name() != "bool" || retval.get_max_possible() == 0);
00664
00665
00666
00667
00668
00669 retval.internal->enquire = this;
00670
00671 return retval;
00672 }
00673
00674 ESet
00675 Enquire::Internal::get_eset(Xapian::termcount maxitems,
00676 const RSet & rset, int flags, double k,
00677 const ExpandDecider * edecider) const
00678 {
00679 ESet retval;
00680
00681 OmExpand expand(db);
00682 RSetI rseti(db, rset);
00683
00684 DEBUGLINE(API, "rset size is " << rset.size());
00685
00686
00687
00688
00689 AutoPtr<ExpandDecider> decider_noquery;
00690 AutoPtr<ExpandDecider> decider_andnoquery;
00691
00692 if (!query.empty() && !(flags & Enquire::INCLUDE_QUERY_TERMS)) {
00693 AutoPtr<ExpandDecider> temp1(
00694 new ExpandDeciderFilterTerms(query.get_terms_begin(),
00695 query.get_terms_end()));
00696 decider_noquery = temp1;
00697
00698 if (edecider) {
00699 AutoPtr<ExpandDecider> temp2(
00700 new ExpandDeciderAnd(decider_noquery.get(), edecider));
00701 decider_andnoquery = temp2;
00702 edecider = decider_andnoquery.get();
00703 } else {
00704 edecider = decider_noquery.get();
00705 }
00706 }
00707
00708 expand.expand(maxitems, retval, &rseti, edecider,
00709 bool(flags & Enquire::USE_EXACT_TERMFREQ), k);
00710
00711 return retval;
00712 }
00713
00714 class ByQueryIndexCmp {
00715 private:
00716 typedef map<string, unsigned int> tmap_t;
00717 const tmap_t &tmap;
00718 public:
00719 ByQueryIndexCmp(const tmap_t &tmap_) : tmap(tmap_) {}
00720 bool operator()(const string &left,
00721 const string &right) const {
00722 tmap_t::const_iterator l, r;
00723 l = tmap.find(left);
00724 r = tmap.find(right);
00725 Assert((l != tmap.end()) && (r != tmap.end()));
00726
00727 return l->second < r->second;
00728 }
00729 };
00730
00731 TermIterator
00732 Enquire::Internal::get_matching_terms(Xapian::docid did) const
00733 {
00734 if (query.empty())
00735 throw Xapian::InvalidArgumentError("get_matching_terms with empty query");
00736
00737
00738
00739 TermIterator qt = query.get_terms_begin();
00740 TermIterator qt_end = query.get_terms_end();
00741
00742
00743
00744
00745 map<string, unsigned int> tmap;
00746 unsigned int index = 1;
00747 for ( ; qt != qt_end; qt++) {
00748 if (tmap.find(*qt) == tmap.end())
00749 tmap[*qt] = index++;
00750 }
00751
00752 vector<string> matching_terms;
00753
00754 TermIterator docterms = db.termlist_begin(did);
00755 TermIterator docterms_end = db.termlist_end(did);
00756 while (docterms != docterms_end) {
00757 string term = *docterms;
00758 map<string, unsigned int>::iterator t = tmap.find(term);
00759 if (t != tmap.end()) matching_terms.push_back(term);
00760 docterms++;
00761 }
00762
00763
00764 sort(matching_terms.begin(), matching_terms.end(), ByQueryIndexCmp(tmap));
00765
00766 return TermIterator(new VectorTermList(matching_terms.begin(),
00767 matching_terms.end()));
00768 }
00769
00770 TermIterator
00771 Enquire::Internal::get_matching_terms(const MSetIterator &it) const
00772 {
00773
00774
00775 return get_matching_terms(*it);
00776 }
00777
00778 string
00779 Enquire::Internal::get_description() const
00780 {
00781 string description = db.get_description();
00782 description += ", ";
00783 description += query.get_description();
00784 return description;
00785 }
00786
00787
00788
00789 void
00790 Enquire::Internal::request_doc(const Xapian::Internal::MSetItem &item) const
00791 {
00792 try {
00793 unsigned int multiplier = db.internal.size();
00794
00795 Xapian::docid realdid = (item.did - 1) / multiplier + 1;
00796 Xapian::doccount dbnumber = (item.did - 1) % multiplier;
00797
00798 db.internal[dbnumber]->request_document(realdid);
00799 } catch (Error & e) {
00800 if (errorhandler) (*errorhandler)(e);
00801 throw;
00802 }
00803 }
00804
00805 Document
00806 Enquire::Internal::read_doc(const Xapian::Internal::MSetItem &item) const
00807 {
00808 try {
00809 unsigned int multiplier = db.internal.size();
00810
00811 Xapian::docid realdid = (item.did - 1) / multiplier + 1;
00812 Xapian::doccount dbnumber = (item.did - 1) % multiplier;
00813
00814 Xapian::Document::Internal *doc;
00815 doc = db.internal[dbnumber]->collect_document(realdid);
00816 return Document(doc);
00817 } catch (Error & e) {
00818 if (errorhandler) (*errorhandler)(e);
00819 throw;
00820 }
00821 }
00822
00823 void
00824 Enquire::Internal::register_match_decider(const string &,
00825 const MatchDecider *)
00826 {
00827 }
00828
00829
00830
00831 Enquire::Enquire(const Enquire & other) : internal(other.internal)
00832 {
00833 DEBUGAPICALL(void, "Xapian::Enquire::Enquire", other);
00834 }
00835
00836 void
00837 Enquire::operator=(const Enquire & other)
00838 {
00839 DEBUGAPICALL(void, "Xapian::Enquire::operator=", other);
00840 internal = other.internal;
00841 }
00842
00843 Enquire::Enquire(const Database &databases, ErrorHandler * errorhandler)
00844 : internal(new Internal(databases, errorhandler))
00845 {
00846 DEBUGAPICALL(void, "Xapian::Enquire::Enquire", databases);
00847 }
00848
00849 Enquire::~Enquire()
00850 {
00851 DEBUGAPICALL(void, "Xapian::Enquire::~Enquire", "");
00852 }
00853
00854 void
00855 Enquire::set_query(const Query & query, termcount len)
00856 {
00857 DEBUGAPICALL(void, "Xapian::Enquire::set_query", query << ", " << len);
00858 internal->set_query(query, len);
00859 }
00860
00861 const Query &
00862 Enquire::get_query() const
00863 {
00864 DEBUGAPICALL(const Xapian::Query &, "Xapian::Enquire::get_query", "");
00865 try {
00866 RETURN(internal->get_query());
00867 } catch (Error & e) {
00868 if (internal->errorhandler) (*internal->errorhandler)(e);
00869 throw;
00870 }
00871 }
00872
00873 void
00874 Enquire::set_weighting_scheme(const Weight &weight_)
00875 {
00876 DEBUGAPICALL(void, "Xapian::Enquire::set_weighting_scheme", "[Weight]");
00877 delete internal->weight;
00878 internal->weight = weight_.clone();
00879 }
00880
00881 void
00882 Enquire::set_collapse_key(Xapian::valueno collapse_key)
00883 {
00884 internal->collapse_key = collapse_key;
00885 }
00886
00887 void
00888 Enquire::set_docid_order(Enquire::docid_order order)
00889 {
00890 internal->order = order;
00891 }
00892
00893 void
00894 Enquire::set_cutoff(Xapian::percent percent_cutoff, Xapian::weight weight_cutoff)
00895 {
00896 internal->percent_cutoff = percent_cutoff;
00897 internal->weight_cutoff = weight_cutoff;
00898 }
00899
00900 void
00901 Enquire::set_sort_by_relevance()
00902 {
00903 internal->sort_by = Internal::REL;
00904 }
00905
00906 void
00907 Enquire::set_sort_by_value(Xapian::valueno sort_key, bool ascending)
00908 {
00909 internal->sorter = NULL;
00910 internal->sort_key = sort_key;
00911 internal->sort_by = Internal::VAL;
00912 internal->sort_value_forward = ascending;
00913 }
00914
00915 void
00916 Enquire::set_sort_by_value_then_relevance(Xapian::valueno sort_key,
00917 bool ascending)
00918 {
00919 internal->sorter = NULL;
00920 internal->sort_key = sort_key;
00921 internal->sort_by = Internal::VAL_REL;
00922 internal->sort_value_forward = ascending;
00923 }
00924
00925 void
00926 Enquire::set_sort_by_relevance_then_value(Xapian::valueno sort_key,
00927 bool ascending)
00928 {
00929 internal->sorter = NULL;
00930 internal->sort_key = sort_key;
00931 internal->sort_by = Internal::REL_VAL;
00932 internal->sort_value_forward = ascending;
00933 }
00934
00935 void
00936 Enquire::set_sort_by_key(Xapian::Sorter * sorter, bool ascending)
00937 {
00938 if (sorter == NULL)
00939 throw Xapian::InvalidArgumentError("sorter can't be NULL");
00940 internal->sorter = sorter;
00941 internal->sort_by = Internal::VAL;
00942 internal->sort_value_forward = ascending;
00943 }
00944
00945 void
00946 Enquire::set_sort_by_key_then_relevance(Xapian::Sorter * sorter, bool ascending)
00947 {
00948 if (sorter == NULL)
00949 throw Xapian::InvalidArgumentError("sorter can't be NULL");
00950 internal->sorter = sorter;
00951 internal->sort_by = Internal::VAL_REL;
00952 internal->sort_value_forward = ascending;
00953 }
00954
00955 void
00956 Enquire::set_sort_by_relevance_then_key(Xapian::Sorter * sorter, bool ascending)
00957 {
00958 if (sorter == NULL)
00959 throw Xapian::InvalidArgumentError("sorter can't be NULL");
00960 internal->sorter = sorter;
00961 internal->sort_by = Internal::REL_VAL;
00962 internal->sort_value_forward = ascending;
00963 }
00964
00965 MSet
00966 Enquire::get_mset(Xapian::doccount first, Xapian::doccount maxitems,
00967 Xapian::doccount check_at_least, const RSet *rset,
00968 const MatchDecider *mdecider) const
00969 {
00970 return get_mset(first, maxitems, check_at_least, rset, mdecider, NULL);
00971 }
00972
00973 MSet
00974 Enquire::get_mset(Xapian::doccount first, Xapian::doccount maxitems,
00975 Xapian::doccount check_at_least, const RSet *rset,
00976 const MatchDecider *mdecider,
00977 const MatchDecider *matchspy) const
00978 {
00979
00980 DEBUGAPICALL(Xapian::MSet, "Xapian::Enquire::get_mset", first << ", " <<
00981 maxitems << ", " << check_at_least << ", " << rset << ", " <<
00982 mdecider << ", " << matchspy);
00983
00984 try {
00985 RETURN(internal->get_mset(first, maxitems, check_at_least, rset,
00986 mdecider, matchspy));
00987 } catch (Error & e) {
00988 if (internal->errorhandler) (*internal->errorhandler)(e);
00989 throw;
00990 }
00991 }
00992
00993 ESet
00994 Enquire::get_eset(Xapian::termcount maxitems, const RSet & rset, int flags,
00995 double k, const ExpandDecider * edecider) const
00996 {
00997
00998
00999 DEBUGAPICALL(Xapian::ESet, "Xapian::Enquire::get_eset", maxitems << ", " <<
01000 rset << ", " << flags << ", " << k << ", " << edecider);
01001
01002 try {
01003
01004 RETURN(internal->get_eset(maxitems, rset, flags, k, edecider));
01005 } catch (Error & e) {
01006 if (internal->errorhandler) (*internal->errorhandler)(e);
01007 throw;
01008 }
01009 }
01010
01011 TermIterator
01012 Enquire::get_matching_terms_begin(const MSetIterator &it) const
01013 {
01014 DEBUGAPICALL(Xapian::TermIterator, "Xapian::Enquire::get_matching_terms", it);
01015 try {
01016 RETURN(internal->get_matching_terms(it));
01017 } catch (Error & e) {
01018 if (internal->errorhandler) (*internal->errorhandler)(e);
01019 throw;
01020 }
01021 }
01022
01023 TermIterator
01024 Enquire::get_matching_terms_begin(Xapian::docid did) const
01025 {
01026 DEBUGAPICALL(Xapian::TermIterator, "Xapian::Enquire::get_matching_terms", did);
01027 try {
01028 RETURN(internal->get_matching_terms(did));
01029 } catch (Error & e) {
01030 if (internal->errorhandler) (*internal->errorhandler)(e);
01031 throw;
01032 }
01033 }
01034
01035 void
01036 Enquire::register_match_decider(const string &name,
01037 const MatchDecider *mdecider)
01038 {
01039 internal->register_match_decider(name, mdecider);
01040 }
01041
01042 string
01043 Enquire::get_description() const
01044 {
01045 return "Xapian::Enquire(" + internal->get_description() + ")";
01046 }
01047
01048 }