# Copyright (C) 2020-2021 all contributors # License: AGPL-3.0+ # Combine any combination of PublicInbox::Search, # PublicInbox::ExtSearch, and PublicInbox::LeiSearch objects # into one Xapian DB package PublicInbox::LeiXSearch; use strict; use v5.10.1; use parent qw(PublicInbox::LeiSearch); sub new { my ($class) = @_; PublicInbox::Search::load_xapian(); bless { qp_flags => $PublicInbox::Search::QP_FLAGS | PublicInbox::Search::FLAG_PURE_NOT(), }, $class } sub attach_external { my ($self, $ibxish) = @_; # ibxish = ExtSearch or Inbox if (!$ibxish->can('over')) { push @{$self->{remotes}}, $ibxish } if (delete $self->{xdb}) { # XXX: do we need this? # clobber existing {xdb} if amending my $expect = delete $self->{nshard}; my $shards = delete $self->{shards_flat}; scalar(@$shards) == $expect or die "BUG: {nshard}$expect != shards=".scalar(@$shards); my $prev = {}; for my $old_ibxish (@{$self->{shard2ibx}}) { next if $prev == $old_ibxish; $prev = $old_ibxish; my @shards = $old_ibxish->search->xdb_shards_flat; push @{$self->{shards_flat}}, @shards; } my $nr = scalar(@{$self->{shards_flat}}); $nr == $expect or die "BUG: reloaded $nr shards, expected $expect" } my @shards = $ibxish->search->xdb_shards_flat; push @{$self->{shards_flat}}, @shards; push(@{$self->{shard2ibx}}, $ibxish) for (@shards); } # called by PublicInbox::Search::xdb sub xdb_shards_flat { @{$_[0]->{shards_flat}} } # like over->get_art sub smsg_for { my ($self, $mitem) = @_; # cf. https://trac.xapian.org/wiki/FAQ/MultiDatabaseDocumentID my $nshard = $self->{nshard}; my $docid = $mitem->get_docid; my $shard = ($docid - 1) % $nshard; my $num = int(($docid - 1) / $nshard) + 1; my $smsg = $self->{shard2ibx}->[$shard]->over->get_art($num); $smsg->{docid} = $docid; $smsg; } sub recent { my ($self, $qstr, $opt) = @_; $opt //= {}; $opt->{relevance} //= -2; $self->mset($qstr //= 'bytes:1..', $opt); } 1;