]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/Search.pm
fixup Plack-related requires
[public-inbox.git] / lib / PublicInbox / Search.pm
index 695d56b376daaf1138e772bedec5132ce0734bff..0f7815fb610124ece7bbbc8867e93199e085490e 100644 (file)
@@ -1,14 +1,22 @@
 # Copyright (C) 2015 all contributors <meta@public-inbox.org>
 # License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
 # based on notmuch, but with no concept of folders, files or flags
+#
+# Read-only search interface for use by the web and NNTP interfaces
 package PublicInbox::Search;
 use strict;
 use warnings;
-use constant TS => 0;
+
+# values for searching
+use constant TS => 0; # timestamp
+use constant NUM => 1; # NNTP article number
+use constant BYTES => 2; # :bytes as defined in RFC 3977
+use constant LINES => 3; # :lines as defined in RFC 3977
+
 use Search::Xapian qw/:standard/;
 use PublicInbox::SearchMsg;
 use Email::MIME;
-use PublicInbox::MID qw/mid_clean mid_compress/;
+use PublicInbox::MID qw/mid_clean id_compress/;
 
 # This is English-only, everything else is non-standard and may be confused as
 # a prefix common in patch emails
@@ -19,15 +27,16 @@ use constant {
        # SCHEMA_VERSION history
        # 0 - initial
        # 1 - subject_path is lower-cased
-       # 2 - subject_path is mid_compress in the index, only
+       # 2 - subject_path is id_compress in the index, only
        # 3 - message-ID is compressed if it includes '%' (hack!)
        # 4 - change "Re: " normalization, avoid circular Reference ghosts
        # 5 - subject_path drops trailing '.'
        # 6 - preserve References: order in document data
        # 7 - remove references and inreplyto terms
        # 8 - remove redundant/unneeded document data
-       # 9 - disable Message-ID compression
-       SCHEMA_VERSION => 9,
+       # 9 - disable Message-ID compression (SHA-1)
+       # 10 - optimize doc for NNTP overviews
+       SCHEMA_VERSION => 10,
 
        # n.b. FLAG_PURE_NOT is expensive not suitable for a public website
        # as it could become a denial-of-service vector
@@ -97,7 +106,7 @@ sub get_thread {
 
        return { total => 0, msgs => [] } unless $smsg;
        my $qtid = Search::Xapian::Query->new(xpfx('thread').$smsg->thread_id);
-       my $path = mid_compress($smsg->path);
+       my $path = id_compress($smsg->path);
        my $qsub = Search::Xapian::Query->new(xpfx('path').$path);
        my $query = Search::Xapian::Query->new(OP_OR, $qtid, $qsub);
        $self->do_enquire($query, $opts);
@@ -168,6 +177,30 @@ sub date_range_processor {
        $_[0]->{drp} ||= Search::Xapian::DateValueRangeProcessor->new(TS);
 }
 
+sub num_range_processor {
+       $_[0]->{nrp} ||= Search::Xapian::NumberValueRangeProcessor->new(NUM);
+}
+
+# only used for NNTP server
+sub query_xover {
+       my ($self, $beg, $end, $offset) = @_;
+       my $enquire = $self->enquire;
+       my $qp = Search::Xapian::QueryParser->new;
+       $qp->set_database($self->{xdb});
+       $qp->add_valuerangeprocessor($self->num_range_processor);
+       my $query = $qp->parse_query("$beg..$end", QP_FLAGS);
+       $query = Search::Xapian::Query->new(OP_AND, $mail_query, $query);
+       $enquire->set_query($query);
+       $enquire->set_sort_by_value(NUM, 0);
+       my $limit = 200;
+       my $mset = $enquire->get_mset($offset, $limit);
+       my @msgs = map {
+               PublicInbox::SearchMsg->load_doc($_->get_document);
+       } $mset->items;
+
+       { total => $mset->get_matches_estimated, msgs => \@msgs }
+}
+
 sub lookup_message {
        my ($self, $mid) = @_;
        $mid = mid_clean($mid);