#!/usr/bin/perl # vim: set ai et sw=3 ts=3 nu: # # Queries Solr # # by Pascal Bleser # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or (at # your option) any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, # USA. use strict; use warnings; use Getopt::Long; use List::Util qw(max); use Text::Wrap; my $show_url = undef; my $show_description = undef; my $max_results = 10; my $offset = 0; my $distribution = undef; my $arch = undef; my $repoid = undef; my $log = undef; my $with_devel = undef; my $with_lang = undef; my $with_doc = undef; GetOptions( 'u|url' => \$show_url, 'l|length=s' => \$max_results, 'o|offset=s' => \$offset, 'log=s' => \$log, 'desc|descr|description' => \$show_description, 'd|dist=s' => \$distribution, 'a|arch=s' => \$arch, 'r|repo=s' => \$repoid, 'devel' => \$with_devel, 'lang' => \$with_lang, 'doc' => \$with_doc, ); die "must specify a query term" unless scalar(@ARGV) > 0; my $q = join(" ", @ARGV); use WebService::Solr; my $solr = WebService::Solr->new("http://localhost:8983/solr", { autocommit => 0, }); my @fq = (); push(@fq, '-tag:devel') unless $with_devel; push(@fq, '-tag:lang') unless $with_lang; push(@fq, '-tag:doc') unless $with_doc; push(@fq, '+distversion:'.$distribution) if defined $distribution; push(@fq, '+arch:'.$arch) if defined $arch; push(@fq, '+repoid:'.$repoid) if defined $repoid; my $delim_pre = '{!<'; my $delim_post = '>!}'; my $result = $solr->search($q, { 'fl' => 'name^10.0,file^8.0,file_stopped^8.0,*,score', 'hl' => 'true', 'hl.fl' => 'name,summary,description,file,file_stopped', 'hl.simple.pre' => $delim_pre, 'hl.simple.post' => $delim_post, 'hl.fragsize' => '50000', 'hl.snippets' => '3', 'hl.requireFieldMatch' => 'false', 'hl.usePhraseHighlighter'=> 'false', 'fq' => join(' ', @fq), 'rows' => $max_results, 'start' => $offset, }); my @docs = $result->docs; if (scalar(@docs) < 1) { print "No results found for \"$q\"\n"; exit 0; } { my $p = $result->pager; my $r1 = (($p->current_page() - 1) * $p->entries_per_page()) + 1; my $r2 = $r1 + (scalar(@docs) - 1); print "Showing results ", $r1, " to ", $r2, " out of ", $p->total_entries(), "\n"; } sub hl($;$) { my $s = shift; my $bg = shift // ''; $s =~ s/\Q$delim_pre\E(.+?)\Q$delim_post\E/\033[33;1m$1\033[0m$bg/g; return $s; } sub f($$;$) { my $doc = shift; my $name = shift; my $bg = shift // ""; my $value = $doc->value_for($name); my $id = $doc->value_for('sha'); my $hl = $result->content()->{highlighting}; if (exists $hl->{$id} and exists $hl->{$id}->{$name}) { $value = hl(join(' ', @{$hl->{$id}->{$name}})); } return $value; } sub ff($$;$) { my $doc = shift; my $name = shift; my $bg = shift // ""; my @values = $doc->values_for($name); my $id = $doc->value_for('sha'); my $hl = $result->content()->{highlighting}; if (exists $hl->{$id} and exists $hl->{$id}->{$name}) { @values = (); foreach (@{$hl->{$id}->{$name}}) { push(@values, hl($_)); } } return \@values; } #$Text::Wrap::Columns = 100; foreach my $d (@docs) { print "\033[42m» ", join("-", map { "\033[1m".$_."\033[0;42m" } map { f($d, $_, "\033[42;1m") } qw(name version release arch)), " ", "[", f($d, 'distname'), " ", f($d, 'distversion'), " / ", f($d, 'repoid'), "]", "\033[K\033[0m", "\n"; print " ", "\033[4m", f($d, 'summary', "\033[4m"), "\033[0m", "\n"; if ($show_description) { my @descr = split(/[\n\r]+/, f($d, 'description')); print fill(" ", " ", @descr), "\n"; } my $files = ff($d, 'file'); print join("\n", map { " * ".$_ } @$files), "\n" if scalar(@$files) > 0; print "\n"; } if ($log) { open(my $l, '>', $log) or die "failed to create log file \"$log\": $!"; use Data::Dumper; $Data::Dumper::Indent = 2; $Data::Dumper::Varname = 'result'; print $l Dumper($result), "\n"; close($l); }