Skip to content

Commit

Permalink
Move autocomplete queries from model to query module
Browse files Browse the repository at this point in the history
  • Loading branch information
haarg committed Jan 14, 2025
1 parent a35c371 commit 07d0bc3
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 176 deletions.
173 changes: 2 additions & 171 deletions lib/MetaCPAN/Document/File/Set.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,11 @@ package MetaCPAN::Document::File::Set;

use Moose;

use List::Util qw( max );
use MetaCPAN::ESConfig qw( es_doc_path );
use MetaCPAN::Query::Favorite ();
use MetaCPAN::Query::File ();
use MetaCPAN::Query::Release ();
use MetaCPAN::Util qw( true false );
use MetaCPAN::ESConfig qw( es_doc_path );
use MetaCPAN::Util qw( true false );

extends 'ElasticSearchX::Model::Document::Set';

has query_favorite => (
is => 'ro',
isa => 'MetaCPAN::Query::Favorite',
lazy => 1,
builder => '_build_query_favorite',
handles => [qw< agg_by_distributions >],
);

sub _build_query_favorite {
my $self = shift;
return MetaCPAN::Query::Favorite->new( es => $self->es );
}

my @ROGUE_DISTRIBUTIONS = qw(
Acme-DependOnEverything
Bundle-Everything
kurila
perl-5.005_02+apache1.3.3+modperl
perlbench
perl_debug
pod2texi
spodcxx
);

sub find {
my ( $self, $module ) = @_;

Expand Down Expand Up @@ -241,146 +213,5 @@ sub history {
return $search->sort( [ { date => 'desc' } ] );
}

sub _autocomplete {
my ( $self, $query ) = @_;

my $search_size = 100;

my $sugg_res = $self->es->search(
es_doc_path('file'),
body => {
suggest => {
documentation => {
text => $query,
completion => {
field => "suggest",
size => $search_size,
},
},
}
},
);

my %docs;
for my $suggest ( @{ $sugg_res->{suggest}{documentation}[0]{options} } ) {
$docs{ $suggest->{text} } = max grep {defined}
( $docs{ $suggest->{text} }, $suggest->{score} );
}

my $res = $self->es->search(
es_doc_path('file'),
body => {
query => {
bool => {
must => [
{ term => { indexed => true } },
{ term => { authorized => true } },
{ term => { status => 'latest' } },
{ terms => { documentation => [ keys %docs ] } },
],
must_not => [
{
terms => { distribution => \@ROGUE_DISTRIBUTIONS }
},
],
}
},
_source => [ qw(
author
date
deprecated
distribution
documentation
release
) ],
size => $search_size,
},
);

my $hits = $res->{hits}{hits};

my $fav_res
= $self->agg_by_distributions(
[ map $_->{_source}{distribution}, @$hits ] );

my $favs = $fav_res->{favorites};

my %valid = map {
my $source = $_->{_source};
(
$source->{documentation} => {
%$source, favorites => $favs->{ $source->{distribution} },
}
);
} @{ $res->{hits}{hits} };

# remove any exact match, it will be added later
my $exact = delete $valid{$query};

no warnings 'uninitialized';
my @sorted = map { $valid{$_} }
sort {
my $a_data = $valid{$a};
my $b_data = $valid{$b};
$a_data->{deprecated} <=> $b_data->{deprecated}
|| $b_data->{favorites} <=> $a_data->{favorites}
|| $docs{$b} <=> $docs{$a}
|| length($a) <=> length($b)
|| $a cmp $b
}
keys %valid;

return {
took => $sugg_res->{took} + $res->{took} + $fav_res->{took},
suggestions => \@sorted,
};
}

sub autocomplete {
my ( $self, @terms ) = @_;
my $data = $self->_autocomplete( join ' ', @terms );

return {
took => $data->{took},
hits => {
hits => [
map {
my $source = $_;
+{
fields => {
map +( $_ => $source->{$_} ), qw(
documentation
release
author
distribution
),
},
};
} @{ $data->{suggestions} }
],
},
};
}

sub autocomplete_suggester {
my ( $self, @terms ) = @_;
my $data = $self->_autocomplete( join ' ', @terms );

return {
took => $data->{took},
suggestions => [
map +{
author => $_->{author},
date => $_->{date},
deprecated => $_->{deprecated},
distribution => $_->{distribution},
name => $_->{documentation},
release => $_->{release},
},
@{ $data->{suggestions} }
],
};
}

__PACKAGE__->meta->make_immutable;
1;
14 changes: 14 additions & 0 deletions lib/MetaCPAN/Query/Distribution.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ use MetaCPAN::Util qw(hit_total);

with 'MetaCPAN::Query::Role::Common';

sub rogue_list {
return qw(
Acme-DependOnEverything
Bundle-Everything
kurila
perl-5.005_02+apache1.3.3+modperl
perlbench
perl_debug
perl_mlb
pod2texi
spodcxx
);
}

sub get_river_data_by_dist {
my ( $self, $dist ) = @_;

Expand Down
146 changes: 146 additions & 0 deletions lib/MetaCPAN/Query/File.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package MetaCPAN::Query::File;

use MetaCPAN::Moose;

use List::Util qw( max );
use MetaCPAN::ESConfig qw( es_doc_path );
use MetaCPAN::Util qw( hit_total true false );

Expand Down Expand Up @@ -356,5 +357,150 @@ sub find_changes_files {
return $file;
}

sub _autocomplete {
my ( $self, $query ) = @_;

my $search_size = 100;

my $sugg_res = $self->es->search(
es_doc_path('file'),
body => {
suggest => {
documentation => {
text => $query,
completion => {
field => "suggest",
size => $search_size,
},
},
}
},
);

my %docs;
for my $suggest ( @{ $sugg_res->{suggest}{documentation}[0]{options} } ) {
$docs{ $suggest->{text} } = max grep {defined}
( $docs{ $suggest->{text} }, $suggest->{score} );
}

my $res = $self->es->search(
es_doc_path('file'),
body => {
query => {
bool => {
must => [
{ term => { indexed => true } },
{ term => { authorized => true } },
{ term => { status => 'latest' } },
{ terms => { documentation => [ keys %docs ] } },
],
must_not => [
{
terms => {
distribution => [
$self->query->distribution->rogue_list
]
},
},
],
}
},
_source => [ qw(
author
date
deprecated
distribution
documentation
release
) ],
size => $search_size,
},
);

my $hits = $res->{hits}{hits};

my $fav_res
= $self->query->favorite->agg_by_distributions(
[ map $_->{_source}{distribution}, @$hits ] );

my $favs = $fav_res->{favorites};

my %valid = map {
my $source = $_->{_source};
(
$source->{documentation} => {
%$source, favorites => $favs->{ $source->{distribution} },
}
);
} @{ $res->{hits}{hits} };

# remove any exact match, it will be added later
my $exact = delete $valid{$query};

no warnings 'uninitialized';
my @sorted = map { $valid{$_} }
sort {
my $a_data = $valid{$a};
my $b_data = $valid{$b};
$a_data->{deprecated} <=> $b_data->{deprecated}
|| $b_data->{favorites} <=> $a_data->{favorites}
|| $docs{$b} <=> $docs{$a}
|| length($a) <=> length($b)
|| $a cmp $b
}
keys %valid;

return {
took => $sugg_res->{took} + $res->{took} + $fav_res->{took},
suggestions => \@sorted,
};
}

sub autocomplete {
my ( $self, @terms ) = @_;
my $data = $self->_autocomplete( join ' ', @terms );

return {
took => $data->{took},
hits => {
hits => [
map {
my $source = $_;
+{
fields => {
map +( $_ => $source->{$_} ), qw(
documentation
release
author
distribution
),
},
};
} @{ $data->{suggestions} }
],
},
};
}

sub autocomplete_suggester {
my ( $self, @terms ) = @_;
my $data = $self->_autocomplete( join ' ', @terms );

return {
took => $data->{took},
suggestions => [
map +{
author => $_->{author},
date => $_->{date},
deprecated => $_->{deprecated},
distribution => $_->{distribution},
name => $_->{documentation},
release => $_->{release},
},
@{ $data->{suggestions} }
],
};
}

__PACKAGE__->meta->make_immutable;
1;
7 changes: 5 additions & 2 deletions lib/MetaCPAN/Query/Search.pm
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,11 @@ sub build_query {
}
},
],
must_not =>
[ { terms => { distribution => \@ROGUE_DISTRIBUTIONS } }, ],
must_not => [ {
terms => {
distribution => [ $self->query->distribution->rogue_list ]
}
} ],
must => [
{
bool => {
Expand Down
6 changes: 3 additions & 3 deletions lib/MetaCPAN/Server/Controller/Search/Autocomplete.pm
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ has '+type' => ( default => 'file' );
sub get : Local : Path('') : Args(0) {
my ( $self, $c ) = @_;
$c->stash_or_detach(
$self->model($c)->autocomplete( $c->req->param("q") ) );
$c->model('ESQuery')->file->autocomplete( $c->req->param("q") ) );
}

sub suggest : Local : Path('/suggest') : Args(0) {
my ( $self, $c ) = @_;
$c->stash_or_detach(
$self->model($c)->autocomplete_suggester( $c->req->param("q") ) );
$c->stash_or_detach( $c->model('ESQuery')
->file->autocomplete_suggester( $c->req->param("q") ) );
}

1;

0 comments on commit 07d0bc3

Please sign in to comment.