Ticket #216: calcpercent.patch

File calcpercent.patch, 25.7 KB (added by Richard Boulton, 15 years ago)

Patch which adds a method to allow percent calculation to be disabled.

  • xapian-core/matcher/multimatch.cc

     
    55 * Copyright 2002,2003,2004,2005,2006,2007,2008 Olly Betts
    66 * Copyright 2003 Orange PCS Ltd
    77 * Copyright 2003 Sam Liddicott
    8  * Copyright 2007 Lemur Consulting Ltd
     8 * Copyright 2007,2008 Lemur Consulting Ltd
    99 *
    1010 * This program is free software; you can redistribute it and/or
    1111 * modify it under the terms of the GNU General Public License as
     
    180180                       const Xapian::RSet * omrset,
    181181                       Xapian::valueno collapse_key_,
    182182                       int percent_cutoff_, Xapian::weight weight_cutoff_,
     183                       bool need_percentages_,
    183184                       Xapian::Enquire::docid_order order_,
    184185                       Xapian::valueno sort_key_,
    185186                       Xapian::Enquire::Internal::sort_setting sort_by_,
     
    190191                       const Xapian::Weight * weight_)
    191192        : db(db_), query(query_),
    192193          collapse_key(collapse_key_), percent_cutoff(percent_cutoff_),
    193           weight_cutoff(weight_cutoff_), order(order_),
     194          weight_cutoff(weight_cutoff_),
     195          need_percentages(need_percentages_),
     196          order(order_),
    194197          sort_key(sort_key_), sort_by(sort_by_),
    195198          sort_value_forward(sort_value_forward_), sorter(sorter_),
    196199          errorhandler(errorhandler_), weight(weight_),
     
    224227                is_remote[i] = true;
    225228                rem_db->set_query(query, qlen, collapse_key, order, sort_key,
    226229                                  sort_by, sort_value_forward, percent_cutoff,
    227                                   weight_cutoff, weight, subrsets[i]);
     230                                  weight_cutoff, need_percentages, weight,
     231                                  subrsets[i]);
    228232                bool decreasing_relevance =
    229233                    (sort_by == REL || sort_by == REL_VAL);
    230234                smatch = new RemoteSubMatch(rem_db, decreasing_relevance);
     
    423427                                           matches_estimated,
    424428                                           max_weight, greatest_wt, items,
    425429                                           termfreqandwts,
    426                                            0));
     430                                           0, false));
    427431        return;
    428432    }
    429433
     
    455459    // Minimum weight an item must have to be worth considering.
    456460    Xapian::weight min_weight = weight_cutoff;
    457461
     462    Assert(percent_cutoff == 0 || need_percentages);
    458463    Xapian::weight percent_factor = percent_cutoff / 100.0;
    459464
    460465    // Table of keys which have been seen already, for collapsing.
     
    773778    delete pl;
    774779
    775780    double percent_scale = 0;
    776     if (!items.empty() && greatest_wt > 0) {
    777         // Find the document with the highest weight, then total up the
    778         // weights for the terms it contains
    779         vector<Xapian::Internal::MSetItem>::const_iterator best;
    780         best = min_element(items.begin(), items.end(), mcmp);
     781    if (need_percentages) {
     782        if (!items.empty() && greatest_wt > 0) {
     783            // Find the document with the highest weight, then total up the
     784            // weights for the terms it contains
     785            vector<Xapian::Internal::MSetItem>::const_iterator best;
     786            best = min_element(items.begin(), items.end(), mcmp);
    781787
    782         if (termfreqandwts.size() > 1) {
    783             Xapian::termcount matching_terms = 0;
    784             map<string,
    785                 Xapian::MSet::Internal::TermFreqAndWeight>::const_iterator i;
     788            if (termfreqandwts.size() > 1) {
     789                Xapian::termcount matching_terms = 0;
     790                map<string,
     791                        Xapian::MSet::Internal::TermFreqAndWeight>::const_iterator i;
    786792
    787             Xapian::TermIterator docterms = db.termlist_begin(best->did);
    788             Xapian::TermIterator docterms_end = db.termlist_end(best->did);
    789             while (docterms != docterms_end) {
    790                 i = termfreqandwts.find(*docterms);
     793                Xapian::TermIterator docterms = db.termlist_begin(best->did);
     794                Xapian::TermIterator docterms_end = db.termlist_end(best->did);
     795                while (docterms != docterms_end) {
     796                    i = termfreqandwts.find(*docterms);
     797                    if (i != termfreqandwts.end()) {
     798                        percent_scale += i->second.termweight;
     799                        ++matching_terms;
     800                        if (matching_terms == termfreqandwts.size()) break;
     801                    }
     802                    ++docterms;
     803                }
     804                // Special case for MatchAll queries
     805                i = termfreqandwts.find("");
    791806                if (i != termfreqandwts.end()) {
    792807                    percent_scale += i->second.termweight;
    793808                    ++matching_terms;
    794                     if (matching_terms == termfreqandwts.size()) break;
    795809                }
    796                 ++docterms;
    797             }
    798             // Special case for MatchAll queries
    799             i = termfreqandwts.find("");
    800             if (i != termfreqandwts.end()) {
    801                 percent_scale += i->second.termweight;
    802                 ++matching_terms;
    803             }
    804             if (matching_terms < termfreqandwts.size()) {
    805                 // OK, work out weight corresponding to 100%
    806                 double denom = 0;
    807                 for (i = termfreqandwts.begin(); i != termfreqandwts.end(); ++i)
    808                     denom += i->second.termweight;
     810                if (matching_terms < termfreqandwts.size()) {
     811                    // OK, work out weight corresponding to 100%
     812                    double denom = 0;
     813                    for (i = termfreqandwts.begin(); i != termfreqandwts.end(); ++i)
     814                        denom += i->second.termweight;
    809815
    810                 DEBUGLINE(MATCH, "denom = " << denom << " percent_scale = " << percent_scale);
    811                 Assert(percent_scale <= denom);
    812                 denom *= greatest_wt;
    813                 Assert(denom > 0);
    814                 percent_scale /= denom;
     816                    DEBUGLINE(MATCH, "denom = " << denom << " percent_scale = " << percent_scale);
     817                    Assert(percent_scale <= denom);
     818                    denom *= greatest_wt;
     819                    Assert(denom > 0);
     820                    percent_scale /= denom;
     821                } else {
     822                    // If all the terms match, the 2 sums of weights cancel
     823                    percent_scale = 1.0 / greatest_wt;
     824                }
    815825            } else {
    816                 // If all the terms match, the 2 sums of weights cancel
     826                // If there's only a single term in the query, the top document
     827                // must score 100%.
    817828                percent_scale = 1.0 / greatest_wt;
    818829            }
    819         } else {
    820             // If there's only a single term in the query, the top document
    821             // must score 100%.
    822             percent_scale = 1.0 / greatest_wt;
    823         }
    824         Assert(percent_scale > 0);
    825         if (percent_cutoff) {
    826             // FIXME: better to sort and binary chop maybe?  we
    827             // could use the sort above to find "best" too.
    828             // Or we could just use a linear scan here instead.
     830            Assert(percent_scale > 0);
     831            if (percent_cutoff) {
     832                // FIXME: better to sort and binary chop maybe?  we
     833                // could use the sort above to find "best" too.
     834                // Or we could just use a linear scan here instead.
    829835
    830             // trim the mset to the correct answer...
    831             Xapian::weight min_wt = percent_factor / percent_scale;
    832             if (!is_heap) {
    833                 is_heap = true;
    834                 make_heap<vector<Xapian::Internal::MSetItem>::iterator,
    835                           MSetCmp>(items.begin(), items.end(), mcmp);
    836             }
    837             while (!items.empty() && items.front().wt < min_wt) {
    838                 pop_heap<vector<Xapian::Internal::MSetItem>::iterator,
    839                          MSetCmp>(items.begin(), items.end(), mcmp);
    840                 Assert(items.back().wt < min_wt);
    841                 items.pop_back();
    842             }
     836                // trim the mset to the correct answer...
     837                Xapian::weight min_wt = percent_factor / percent_scale;
     838                if (!is_heap) {
     839                    is_heap = true;
     840                    make_heap<vector<Xapian::Internal::MSetItem>::iterator,
     841                            MSetCmp>(items.begin(), items.end(), mcmp);
     842                }
     843                while (!items.empty() && items.front().wt < min_wt) {
     844                    pop_heap<vector<Xapian::Internal::MSetItem>::iterator,
     845                            MSetCmp>(items.begin(), items.end(), mcmp);
     846                    Assert(items.back().wt < min_wt);
     847                    items.pop_back();
     848                }
    843849#ifdef XAPIAN_DEBUG_PARANOID
    844             vector<Xapian::Internal::MSetItem>::const_iterator j;
    845             for (j = items.begin(); j != items.end(); ++j) {
    846                 Assert(j->wt >= min_wt);
     850                vector<Xapian::Internal::MSetItem>::const_iterator j;
     851                for (j = items.begin(); j != items.end(); ++j) {
     852                    Assert(j->wt >= min_wt);
     853                }
     854#endif
    847855            }
    848 #endif
     856            percent_scale *= 100.0;
    849857        }
    850         percent_scale *= 100.0;
    851858    }
    852859
    853860    DEBUGLINE(MATCH,
     
    9971004        !collapse_tab.empty()) {
    9981005        // Nicked this formula from above, but for some reason percent_scale
    9991006        // has since been multiplied by 100 so we take that into account
    1000         Xapian::weight min_wt = percent_factor / (percent_scale / 100);
     1007        Xapian::weight min_wt = need_percentages ? 0.0 :
     1008                percent_factor / (percent_scale / 100);
    10011009        vector<Xapian::Internal::MSetItem>::iterator i;
    10021010        for (i = items.begin(); i != items.end() && !collapse_tab.empty(); ++i) {
    10031011            // Is this a collapsed hit?
     
    10301038                                       matches_estimated,
    10311039                                       max_weight, greatest_wt, items,
    10321040                                       termfreqandwts,
    1033                                        percent_scale));
     1041                                       percent_scale,
     1042                                       need_percentages));
    10341043}
    10351044
    10361045// This method is called by branch postlists when they rebalance
  • xapian-core/matcher/localmatch.cc

     
    33 * Copyright 1999,2000,2001 BrightStation PLC
    44 * Copyright 2002 Ananova Ltd
    55 * Copyright 2002,2003,2004,2005,2006,2007,2008 Olly Betts
    6  * Copyright 2007 Lemur Consulting Ltd
     6 * Copyright 2007,2008 Lemur Consulting Ltd
    77 *
    88 * This program is free software; you can redistribute it and/or
    99 * modify it under the terms of the GNU General Public License as
     
    117117                                           double factor)
    118118{
    119119    DEBUGCALL(MATCH, PostList *, "LocalSubMatch::postlist_from_op_leaf_query",
    120               query << ", " << factor);
     120              query->get_description() << ", " << factor);
    121121    Assert(query);
    122122    AssertEq(query->op, Xapian::Query::Internal::OP_LEAF);
    123123    Assert(query->subqs.empty());
     
    140140        Xapian::doccount tf = stats->get_termfreq(query->tname);
    141141        Xapian::weight weight = boolean ? 0 : wt->get_maxpart();
    142142        Xapian::MSet::Internal::TermFreqAndWeight info(tf, weight);
     143        DEBUGLINE(MATCH, "Setting term_info[" << query->tname << "] to (" << tf << ", " << weight << ")");
    143144        term_info.insert(make_pair(query->tname, info));
    144145    } else if (!boolean) {
    145146        i->second.termweight += wt->get_maxpart();
     147        AssertEq(stats->get_termfreq(query->tname), i->second.termfreq);
     148        DEBUGLINE(MATCH, "Increasing term_info[" << query->tname << "] to (" << i->second.termfreq << ", " << i->second.termweight << ")");
    146149    }
    147150
    148151    LeafPostList * pl = db->open_post_list(query->tname);
  • xapian-core/docs/remote_protocol.html

     
    164164<li> <code>MSG_QUERY L&lt;serialised Xapian::Query object&gt;
    165165I&lt;query length&gt; I&lt;collapse key number&gt; &lt;docid order&gt;
    166166I&lt;sort key number&gt; &lt;sort by&gt; B&lt;sort value forward&gt;
    167 &lt;percent cutoff&gt; F&lt;weight cutoff&gt; &lt;serialised Xapian::Weight object&gt; &lt;serialised Xapian::RSet object&gt;</code>
     167&lt;percent cutoff&gt; F&lt;weight cutoff&gt; B&lt;need_percentages&gt; &lt;serialised Xapian::Weight object&gt; &lt;serialised Xapian::RSet object&gt;</code>
    168168<li> <code>REPLY_STATS &lt;serialised Stats object&gt;</code>
    169169<li> <code>MSG_GETMSET I&lt;first&gt; I&lt;max items&gt; I&lt;check at least&gt;
    170170&lt;serialised global Stats object&gt;</code>
  • xapian-core/tests/api_anydb.cc

     
    473473DEFINE_TESTCASE(topercent1, backend) {
    474474    Xapian::Enquire enquire(get_database("apitest_simpledata"));
    475475    enquire.set_query(query("this"));
     476    enquire.set_calculate_percentages(true);
    476477    Xapian::MSet mymset = enquire.get_mset(0, 20);
    477478
    478479    int last_pct = 100;
     
    491492    return true;
    492493}
    493494
     495// tests that the percent functions error if percents weren't calculated
     496DEFINE_TESTCASE(topercent2, backend) {
     497    Xapian::Enquire enquire(get_database("apitest_simpledata"));
     498    enquire.set_query(query("this"));
     499    Xapian::MSet mymset = enquire.get_mset(0, 20);
     500
     501    for (Xapian::MSetIterator i = mymset.begin(); i != mymset.end(); ++i) {
     502        TEST_EXCEPTION(Xapian::InvalidOperationError,
     503                       mymset.convert_to_percent(i));
     504        TEST_EXCEPTION(Xapian::InvalidOperationError,
     505                       i.get_percent());
     506        TEST_EXCEPTION(Xapian::InvalidOperationError,
     507                       mymset.convert_to_percent(i.get_weight()));
     508    }
     509    return true;
     510}
     511
    494512class myExpandFunctor : public Xapian::ExpandDecider {
    495513    public:
    496514        bool operator()(const string & tname) const {
     
    568586
    569587// tests the percent cutoff option
    570588DEFINE_TESTCASE(pctcutoff1, backend) {
    571     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     589    Xapian::Database db(get_database("apitest_simpledata"));
     590    Xapian::Enquire enquire(db);
    572591    enquire.set_query(query(Xapian::Query::OP_OR,
    573592                            "this", "line", "paragraph", "rubbish"));
     593    enquire.set_calculate_percentages(true);
    574594    Xapian::MSet mymset1 = enquire.get_mset(0, 100);
    575595
    576596    if (verbose) {
     
    599619        tout << "Cutoff percent: " << my_pct << "\n";
    600620    }
    601621
     622    enquire = Xapian::Enquire(db);
     623    enquire.set_query(query(Xapian::Query::OP_OR,
     624                            "this", "line", "paragraph", "rubbish"));
    602625    enquire.set_cutoff(my_pct);
    603626    Xapian::MSet mymset2 = enquire.get_mset(0, 100);
    604627
  • xapian-core/include/xapian/enquire.h

     
    44/* Copyright 1999,2000,2001 BrightStation PLC
    55 * Copyright 2001,2002 Ananova Ltd
    66 * Copyright 2002,2003,2004,2005,2006,2007,2008 Olly Betts
     7 * Copyright 2008 Lemur Consulting Ltd
    78 *
    89 * This program is free software; you can redistribute it and/or
    910 * modify it under the terms of the GNU General Public License as
     
    9293        void fetch() const;
    9394
    9495        /** This converts the weight supplied to a percentage score.
     96         *
    9597         *  The return value will be in the range 0 to 100, and will be 0 if
    9698         *  and only if the item did not match the query at all.
     99         *
     100         *  Percentage weight calculation must have been enabled during the
     101         *  match.  See @a Enquire::set_calculate_percentages() for more
     102         *  details.
     103         *
     104         *  @exception InvalidOperationError if percentage weights were not
     105         *  calculated during the match.
    97106         */
    98107        Xapian::percent convert_to_percent(Xapian::weight wt) const;
    99108
    100         /// Return the percentage score for a particular item.
     109        /** Return the percentage score for a particular item.
     110         *
     111         *  The return value will be in the range 0 to 100, and will be 0 if
     112         *  and only if the item did not match the query at all.
     113         *
     114         *  Percentage weight calculation must have been enabled during the
     115         *  match.  See @a Enquire::set_calculate_percentages() for more
     116         *  details.
     117         *
     118         *  @exception InvalidOperationError if percentage weights were not
     119         *  calculated during the match.
     120         */
    101121        Xapian::percent convert_to_percent(const MSetIterator &it) const;
    102122
    103123        /** Return the term frequency of the given query term.
     
    353373
    354374        /** This returns the weight of the document as a percentage score.
    355375         *
    356          *  The return value will be in the range 0 to 100:  0 meaning
    357          *  that the item did not match the query at all.
     376         *  The return value will be in the range 0 to 100, and will be 0 if
     377         *  and only if the item did not match the query at all.
     378         *
     379         *  Percentage weight calculation must have been enabled during the
     380         *  match.  See @a Enquire::set_calculate_percentages() for more
     381         *  details.
     382         *
     383         *  @exception InvalidOperationError if percentage weights were not
     384         *  calculated during the match.
    358385         */
    359386        Xapian::percent get_percent() const;
    360387
     
    731758
    732759        /** Set the percentage and/or weight cutoffs.
    733760         *
     761         *  If a percentage cutoff is specified using this method (ie, the @a
     762         *  percent_cutoff parameter is non zero), percentage weights will be
     763         *  calculated regardless of whether set_calculate_percentages() has
     764         *  been called.
     765         *
    734766         * @param percent_cutoff Minimum percentage score for returned
    735767         *      documents. If a document has a lower percentage score than this,
    736768         *      it will not appear in the MSet.  If your intention is to return
     
    749781         */
    750782        void set_cutoff(Xapian::percent percent_cutoff, Xapian::weight weight_cutoff = 0);
    751783
     784        /** Set whether percentages should be calculated.
     785         *
     786         *  Calculation of percentages involves a (hopefully small) overhead,
     787         *  and percentage values are often not desired.  Therefore, for
     788         *  performance reasons, percentages are not calculated unless
     789         *  explicitly requested.
     790         *
     791         *  @param val true if percentages should be calculated, false if they
     792         *  should not.
     793         */
     794        void set_calculate_percentages(bool val);
     795
    752796        /** Set the sorting to be by relevance only.
    753797         *
    754798         *  This is the default.
  • xapian-core/net/serialise.cc

     
    22 * @brief functions to convert Xapian objects to strings and back
    33 */
    44/* Copyright (C) 2006,2007,2008 Olly Betts
     5 * Copyright (C) 2008 Lemur Consulting Ltd
    56 *
    67 * This program is free software; you can redistribute it and/or modify
    78 * it under the terms of the GNU General Public License as published by
     
    188189    result += serialise_double(mset.get_max_attained());
    189190
    190191    result += serialise_double(mset.internal->percent_factor);
     192    result += encode_length(int(mset.internal->have_percentages));
    191193
    192194    result += encode_length(mset.size());
    193195    for (Xapian::MSetIterator i = mset.begin(); i != mset.end(); ++i) {
     
    226228    Xapian::weight max_attained = unserialise_double(&p, p_end);
    227229
    228230    double percent_factor = unserialise_double(&p, p_end);
     231    bool have_percentages = decode_length(&p, p_end, false);
    229232
    230233    vector<Xapian::Internal::MSetItem> items;
    231234    size_t msize = decode_length(&p, p_end, false);
     
    256259                                       matches_lower_bound,
    257260                                       matches_estimated,
    258261                                       max_possible, max_attained,
    259                                        items, terminfo, percent_factor));
     262                                       items, terminfo, percent_factor,
     263                                       have_percentages));
    260264}
    261265
    262266string
  • xapian-core/net/remoteserver.cc

     
    22 *  @brief Xapian remote backend server base class
    33 */
    44/* Copyright (C) 2006,2007,2008 Olly Betts
    5  * Copyright (C) 2006,2007 Lemur Consulting Ltd
     5 * Copyright (C) 2006,2007,2008 Lemur Consulting Ltd
    66 *
    77 * This program is free software; you can redistribute it and/or modify
    88 * it under the terms of the GNU General Public License as published by
     
    392392        throw Xapian::NetworkError("bad message (weight_cutoff)");
    393393    }
    394394
     395    if (*p < '0' || *p > '1') {
     396        throw Xapian::NetworkError("bad message (need_percentages)");
     397    }
     398    bool need_percentages(*p++ != '0');
     399
    395400    // Unserialise the Weight object.
    396401    len = decode_length(&p, p_end, true);
    397402    map<string, Xapian::Weight *>::const_iterator i;
     
    410415
    411416    Stats local_stats;
    412417    MultiMatch match(*db, query.get(), qlen, &rset, collapse_key,
    413                      percent_cutoff, weight_cutoff, order,
     418                     percent_cutoff, weight_cutoff, need_percentages, order,
    414419                     sort_key, sort_by, sort_value_forward, NULL,
    415420                     NULL, local_stats, wt.get());
    416421
  • xapian-core/common/omenquireinternal.h

     
    33 * Copyright 1999,2000,2001 BrightStation PLC
    44 * Copyright 2001,2002 Ananova Ltd
    55 * Copyright 2002,2003,2004,2005,2006,2007 Olly Betts
     6 * Copyright 2008 Lemur Consulting Ltd
    67 *
    78 * This program is free software; you can redistribute it and/or
    89 * modify it under the terms of the GNU General Public License as
     
    161162
    162163        Xapian::weight weight_cutoff;
    163164
     165        bool calculate_percentages;
     166
    164167        Xapian::valueno sort_key;
    165168        sort_setting sort_by;
    166169        bool sort_value_forward;
     
    209212        /// Factor to multiply weights by to convert them to percentages.
    210213        double percent_factor;
    211214
     215        /// True iff percentage information is available.
     216        bool have_percentages;
     217
    212218    private:
    213219        /** The set of documents which have been requested but not yet
    214220         *  collected.
     
    281287             Xapian::weight max_attained_,
    282288             const vector<Xapian::Internal::MSetItem> &items_,
    283289             const map<string, TermFreqAndWeight> &termfreqandwts_,
    284              Xapian::weight percent_factor_)
     290             Xapian::weight percent_factor_,
     291             bool have_percentages_)
    285292                : percent_factor(percent_factor_),
     293                  have_percentages(have_percentages_),
    286294                  termfreqandwts(termfreqandwts_),
    287295                  items(items_),
    288296                  firstitem(firstitem_),
  • xapian-core/common/multimatch.h

     
    22 *
    33 * Copyright 1999,2000,2001 BrightStation PLC
    44 * Copyright 2002,2003,2004,2005,2006,2007 Olly Betts
     5 * Copyright 2008 Lemur Consulting Ltd
    56 *
    67 * This program is free software; you can redistribute it and/or
    78 * modify it under the terms of the GNU General Public License as
     
    4748
    4849        Xapian::weight weight_cutoff;
    4950
     51        bool need_percentages;
     52
    5053        Xapian::Enquire::docid_order order;
    5154
    5255        Xapian::valueno sort_key;
     
    107110                   Xapian::valueno collapse_key_,
    108111                   int percent_cutoff_,
    109112                   Xapian::weight weight_cutoff_,
     113                   bool need_percentages_,
    110114                   Xapian::Enquire::docid_order order_,
    111115                   Xapian::valueno sort_key_,
    112116                   Xapian::Enquire::Internal::sort_setting sort_by_,
  • xapian-core/common/remote-database.h

     
    22 *  @brief RemoteDatabase is the baseclass for remote database implementations.
    33 */
    44/* Copyright (C) 2006,2007 Olly Betts
    5  * Copyright (C) 2007 Lemur Consulting Ltd
     5 * Copyright (C) 2007,2008 Lemur Consulting Ltd
    66 *
    77 * This program is free software; you can redistribute it and/or
    88 * modify it under the terms of the GNU General Public License as
     
    131131                   Xapian::Enquire::Internal::sort_setting sort_by,
    132132                   bool sort_value_forward,
    133133                   int percent_cutoff, Xapian::weight weight_cutoff,
     134                   bool need_percentages,
    134135                   const Xapian::Weight *wtscheme,
    135136                   const Xapian::RSet &omrset);
    136137
  • xapian-core/api/omenquire.cc

     
    33 * Copyright 1999,2000,2001 BrightStation PLC
    44 * Copyright 2001,2002 Ananova Ltd
    55 * Copyright 2002,2003,2004,2005,2006,2007,2008 Olly Betts
    6  * Copyright 2007 Lemur Consulting Ltd
     6 * Copyright 2007,2008 Lemur Consulting Ltd
    77 *
    88 * This program is free software; you can redistribute it and/or
    99 * modify it under the terms of the GNU General Public License as
     
    344344MSet::Internal::convert_to_percent_internal(Xapian::weight wt) const
    345345{
    346346    DEBUGAPICALL(Xapian::percent, "Xapian::MSet::Internal::convert_to_percent", wt);
     347    if (!have_percentages)
     348        throw Xapian::InvalidOperationError("Percentage weights were not calculated during match");
    347349    if (percent_factor == 0) RETURN(100);
    348350
    349351    // FIXME: + 0.5 ???
     
    612614Enquire::Internal::Internal(const Database &db_, ErrorHandler * errorhandler_)
    613615  : db(db_), query(), collapse_key(Xapian::BAD_VALUENO),
    614616    order(Enquire::ASCENDING), percent_cutoff(0), weight_cutoff(0),
     617    calculate_percentages(false),
    615618    sort_key(Xapian::BAD_VALUENO), sort_by(REL), sort_value_forward(true),
    616619    sorter(0), errorhandler(errorhandler_), weight(0)
    617620{
     
    653656        weight = new BM25Weight;
    654657    }
    655658
     659    bool need_percentages = calculate_percentages || (percent_cutoff != 0);
    656660    Stats stats;
    657661    ::MultiMatch match(db, query.internal.get(), qlen, rset, collapse_key,
    658                        percent_cutoff, weight_cutoff,
     662                       percent_cutoff, weight_cutoff, need_percentages,
    659663                       order, sort_key, sort_by, sort_value_forward, sorter,
    660664                       errorhandler, stats, weight);
    661665    // Run query and put results into supplied Xapian::MSet object.
     
    907911}
    908912
    909913void
     914Enquire::set_calculate_percentages(bool val)
     915{
     916    internal->calculate_percentages = val;
     917}
     918
     919void
    910920Enquire::set_sort_by_relevance()
    911921{
    912922    internal->sort_by = Internal::REL;
  • xapian-core/backends/remote/remote-database.cc

     
    22 *  @brief Remote backend database class
    33 */
    44/* Copyright (C) 2006,2007,2008 Olly Betts
    5  * Copyright (C) 2007 Lemur Consulting Ltd
     5 * Copyright (C) 2007,2008 Lemur Consulting Ltd
    66 *
    77 * This program is free software; you can redistribute it and/or
    88 * modify it under the terms of the GNU General Public License as
     
    440440                         Xapian::Enquire::Internal::sort_setting sort_by,
    441441                         bool sort_value_forward,
    442442                         int percent_cutoff, Xapian::weight weight_cutoff,
     443                         bool need_percentages,
    443444                         const Xapian::Weight *wtscheme,
    444445                         const Xapian::RSet &omrset)
    445446{
     
    456457    message += char('0' + sort_value_forward);
    457458    message += char(percent_cutoff);
    458459    message += serialise_double(weight_cutoff);
     460    message += char('0' + need_percentages);
    459461
    460462    tmp = wtscheme->name();
    461463    message += encode_length(tmp.size());
  • xapian-bindings/xapian.i

     
    375375    void set_docid_order(docid_order order);
    376376
    377377    void set_cutoff(int percent_cutoff, weight weight_cutoff = 0);
     378    void set_calculate_percentages(bool val);
    378379
    379380    void set_sort_by_relevance();
    380381    void set_sort_by_value(Xapian::valueno sort_key, bool ascending = true);