430
bool RPackageLister::xapianIndexNeedsUpdate()
434
if(_config->FindB("Debug::Synaptic::Xapian",false))
435
std::cerr << "xapainIndexNeedsUpdate()" << std::endl;
437
// check the xapian index
438
if(FileExists("/usr/sbin/update-apt-xapian-index") &&
439
(!_xapianDatabase )) {
440
if(_config->FindB("Debug::Synaptic::Xapian",false))
441
std::cerr << "xapain index not build yet" << std::endl;
445
// compare timestamps, rebuild everytime, its now cheap(er)
446
// because we use u-a-x-i --update
447
stat(_config->FindFile("Dir::Cache::pkgcache").c_str(), &buf);
448
if(ept::axi::timestamp() < buf.st_mtime) {
449
if(_config->FindB("Debug::Synaptic::Xapian",false))
450
std::cerr << "xapian outdated "
451
<< buf.st_mtime - ept::axi::timestamp() << std::endl;
458
bool RPackageLister::openXapianIndex()
461
delete _xapianDatabase;
463
_xapianDatabase = new Xapian::Database(ept::axi::path_db());
464
} catch (Xapian::DatabaseOpeningError) {
424
471
void RPackageLister::applyInitialSelection()
1943
bool RPackageLister::limitBySearch(string searchString)
1945
//cerr << "limitBySearch(): " << searchString << endl;
1946
if (ept::axi::timestamp() == 0)
1948
return xapianSearch(searchString);
1951
bool RPackageLister::xapianSearch(string unsplitSearchString)
1953
//std::cerr << "RPackageLister::xapianSearch()" << std::endl;
1954
static const int defaultQualityCutoff = 15;
1955
int qualityCutoff = _config->FindI("Synaptic::Xapian::qualityCutoff",
1956
defaultQualityCutoff);
1957
if (ept::axi::timestamp() == 0)
1961
int maxItems = _xapianDatabase->get_doccount();
1962
Xapian::Enquire enquire(*_xapianDatabase);
1963
Xapian::QueryParser parser;
1964
parser.set_database(*_xapianDatabase);
1965
parser.add_prefix("name","XP");
1966
parser.add_prefix("section","XS");
1967
// default op is AND to narrow down the resultset
1968
parser.set_default_op( Xapian::Query::OP_AND );
1970
/* Workaround to allow searching an hyphenated package name using a prefix (name:)
1972
* Xapian currently doesn't support wildcard for boolean prefix and
1973
* doesn't handle implicit wildcards at the end of hypenated phrases.
1975
* e.g searching for name:ubuntu-res will be equivalent to 'name:ubuntu res*'
1976
* however 'name:(ubuntu* res*) won't return any result because the
1977
* index is built with the full package name
1979
// Always search for the package name
1980
string xpString = "name:";
1981
string::size_type pos = unsplitSearchString.find_first_of(" ,;");
1983
xpString += unsplitSearchString.substr(0,pos);
1985
xpString += unsplitSearchString;
1987
Xapian::Query xpQuery = parser.parse_query(xpString);
1990
while ( (pos = unsplitSearchString.find("-", pos)) != string::npos ) {
1991
unsplitSearchString.replace(pos, 1, " ");
1995
if(_config->FindB("Debug::Synaptic::Xapian",false))
1996
std::cerr << "searching for : " << unsplitSearchString << std::endl;
1999
// apply a weight factor to XP term to increase relevancy on package name
2000
Xapian::Query query = parser.parse_query(unsplitSearchString,
2001
Xapian::QueryParser::FLAG_WILDCARD |
2002
Xapian::QueryParser::FLAG_BOOLEAN |
2003
Xapian::QueryParser::FLAG_PARTIAL);
2004
query = Xapian::Query(Xapian::Query::OP_OR, query,
2005
Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT, xpQuery, 3));
2006
enquire.set_query(query);
2007
Xapian::MSet matches = enquire.get_mset(0, maxItems);
2009
if(_config->FindB("Debug::Synaptic::Xapian",false)) {
2010
cerr << "enquire: " << enquire.get_description() << endl;
2011
cerr << "matches estimated: " << matches.get_matches_estimated() << " results found" << endl;
2014
// Retrieve the results
2015
int top_percent = 0;
2016
_viewPackages.clear();
2017
for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i)
2019
RPackage* pkg = getPackage(i.get_document().get_data());
2020
// Filter out results that apt doesn't know
2021
if (!pkg || !_selectedView->hasPackage(pkg))
2024
// Save the confidence interval of the top value, to use it as
2025
// a reference to compute an adaptive quality cutoff
2026
if (top_percent == 0)
2027
top_percent = i.get_percent();
2029
// Stop producing if the quality goes below a cutoff point
2030
if (i.get_percent() < qualityCutoff * top_percent / 100)
2032
cerr << "Discarding: " << i.get_percent() << " over " << qualityCutoff * top_percent / 100 << endl;
2036
if(_config->FindB("Debug::Synaptic::Xapian",false))
2037
cerr << i.get_rank() + 1 << ": " << i.get_percent() << "% docid=" << *i << " [" << i.get_document().get_data() << "]" << endl;
2038
_viewPackages.push_back(pkg);
2040
// re-apply sort criteria only if an explicit search is set
2041
if (_sortMode != LIST_SORT_DEFAULT)
2042
sortPackages(_sortMode);
2044
} catch (const Xapian::Error & error) {
2045
/* We are here if a Xapian call failed. The main cause is a parser exception.
2046
* The error message is always in English currently.
2047
* The possible parser errors are:
2048
* Unknown range operation
2050
* Syntax: <expression> AND <expression>
2051
* Syntax: <expression> AND NOT <expression>
2052
* Syntax: <expression> NOT <expression>
2053
* Syntax: <expression> OR <expression>
2054
* Syntax: <expression> XOR <expression>
2056
cerr << "Exception in RPackageLister::xapianSearch():" << error.get_msg() << endl;
2061
bool RPackageLister::limitBySearch(string searchString)
2066
bool RPackageLister::xapianSearch(string searchString)
1886
2073
// vim:ts=3:sw=3:et