When searching over multiple databases, how do I convert an MSet entry to the sub-database and docid in it?
C/C++
Document ids in the combined database are interleaved, so if docid_combined
is the docid from the MSet, and db
is the Xapian::Database
object then the following C++ code implements this:
shard_number = (docid_combined - 1) % db.size(); // First shard is 0. docid_shard = (docid_combined - 1) / db.size() + 1;
This makes use of the Database::size()
method which is available in Xapian 1.4.12 and later. If you need to support older versions you'll need to keep track of the number of shards yourself. That can be fiddly in some cases, because Database::add_database()
"flattens" the added database, so doesn't necessarily increase the number of shards by one - if could not increase it (if the added database contains no shards) or increase it by more than one (if the added database contains multiple shards).
Other languages
If you want to implement this in another language you should be able to adapt the C/C++ code above. Note that
%
means modulus in the above and /
an integer division (truncating any fractional part towards zero).
Omega 1.4.7 and later
If you need to do this in an Omega template then 1.4.7 added $subdb{DOCID}
and $subid{DOCID}
to give you the name of the sub-database containing DOCID and the corresponding docid in that sub-database. You can use $subdb
and $subid
if you just want to use the current document in the hitlist.
Omega 1.4.6 and older
If you need to support older versions of Omega, this is equivalent to $subdb
without an argument list:
$slice{$split{/,$dbname},$mod{$sub{$id,1},$length{$split{/,$dbname}}}}
And this to $subid
without an argument list:
$add{$div{$sub{$id,1},$length{$split{/,$dbname}}},1}