|
1 | 1 | package MetaCPAN::Document::Favorite::Set; |
2 | 2 |
|
3 | | -use strict; |
4 | | -use warnings; |
5 | | - |
6 | 3 | use Moose; |
7 | | -extends 'ElasticSearchX::Model::Document::Set'; |
8 | | - |
9 | | -use MetaCPAN::Util qw( single_valued_arrayref_to_scalar ); |
10 | | - |
11 | | -sub by_user { |
12 | | - my ( $self, $user, $size ) = @_; |
13 | | - $size ||= 250; |
14 | | - |
15 | | - my $favs = $self->es->search( |
16 | | - index => $self->index->name, |
17 | | - type => 'favorite', |
18 | | - body => { |
19 | | - query => { term => { user => $user } }, |
20 | | - fields => [qw( author date distribution )], |
21 | | - sort => ['distribution'], |
22 | | - size => $size, |
23 | | - } |
24 | | - ); |
25 | | - return {} unless $favs->{hits}{total}; |
26 | | - my $took = $favs->{took}; |
27 | | - |
28 | | - my @favs = map { $_->{fields} } @{ $favs->{hits}{hits} }; |
29 | | - |
30 | | - single_valued_arrayref_to_scalar( \@favs ); |
31 | | - |
32 | | - # filter out backpan only distributions |
33 | | - |
34 | | - my $no_backpan = $self->es->search( |
35 | | - index => $self->index->name, |
36 | | - type => 'release', |
37 | | - body => { |
38 | | - query => { |
39 | | - bool => { |
40 | | - must => [ |
41 | | - { terms => { status => [qw( cpan latest )] } }, |
42 | | - { |
43 | | - terms => { |
44 | | - distribution => |
45 | | - [ map { $_->{distribution} } @favs ] |
46 | | - } |
47 | | - }, |
48 | | - ] |
49 | | - } |
50 | | - }, |
51 | | - fields => ['distribution'], |
52 | | - size => scalar(@favs), |
53 | | - } |
54 | | - ); |
55 | | - $took += $no_backpan->{took}; |
56 | | - |
57 | | - if ( $no_backpan->{hits}{total} ) { |
58 | | - my %has_no_backpan = map { $_->{fields}{distribution}[0] => 1 } |
59 | | - @{ $no_backpan->{hits}{hits} }; |
60 | | - |
61 | | - @favs = grep { exists $has_no_backpan{ $_->{distribution} } } @favs; |
62 | | - } |
63 | | - |
64 | | - return { favorites => \@favs, took => $took }; |
65 | | -} |
66 | 4 |
|
67 | | -sub users_by_distribution { |
68 | | - my ( $self, $distribution ) = @_; |
| 5 | +use MetaCPAN::Query::Favorite; |
69 | 6 |
|
70 | | - my $favs = $self->es->search( |
71 | | - index => $self->index->name, |
72 | | - type => 'favorite', |
73 | | - body => { |
74 | | - query => { term => { distribution => $distribution } }, |
75 | | - _source => ['user'], |
76 | | - size => 1000, |
77 | | - } |
78 | | - ); |
79 | | - return {} unless $favs->{hits}{total}; |
80 | | - |
81 | | - my @plusser_users = map { $_->{_source}{user} } @{ $favs->{hits}{hits} }; |
82 | | - |
83 | | - single_valued_arrayref_to_scalar( \@plusser_users ); |
84 | | - |
85 | | - return { users => \@plusser_users }; |
86 | | -} |
87 | | - |
88 | | -sub agg_by_distributions { |
89 | | - my ( $self, $distributions, $user ) = @_; |
90 | | - return unless $distributions; |
91 | | - |
92 | | - my $body = { |
93 | | - size => 0, |
94 | | - query => { |
95 | | - terms => { 'distribution' => $distributions } |
96 | | - }, |
97 | | - aggregations => { |
98 | | - favorites => { |
99 | | - terms => { |
100 | | - field => 'distribution', |
101 | | - size => scalar @{$distributions}, |
102 | | - }, |
103 | | - }, |
104 | | - $user |
105 | | - ? ( |
106 | | - myfavorites => { |
107 | | - filter => { term => { 'user' => $user } }, |
108 | | - aggregations => { |
109 | | - enteries => { |
110 | | - terms => { field => 'distribution' } |
111 | | - } |
112 | | - } |
113 | | - } |
114 | | - ) |
115 | | - : (), |
116 | | - } |
117 | | - }; |
118 | | - |
119 | | - my $ret = $self->es->search( |
120 | | - index => $self->index->name, |
121 | | - type => 'favorite', |
122 | | - body => $body, |
123 | | - ); |
124 | | - |
125 | | - my %favorites = map { $_->{key} => $_->{doc_count} } |
126 | | - @{ $ret->{aggregations}{favorites}{buckets} }; |
127 | | - |
128 | | - my %myfavorites; |
129 | | - if ($user) { |
130 | | - %myfavorites = map { $_->{key} => $_->{doc_count} } |
131 | | - @{ $ret->{aggregations}{myfavorites}{entries}{buckets} }; |
132 | | - } |
133 | | - |
134 | | - return { |
135 | | - favorites => \%favorites, |
136 | | - myfavorites => \%myfavorites, |
137 | | - took => $ret->{took}, |
138 | | - }; |
139 | | -} |
140 | | - |
141 | | -sub recent { |
142 | | - my ( $self, $page, $size ) = @_; |
143 | | - $page //= 1; |
144 | | - $size //= 100; |
145 | | - |
146 | | - my $favs = $self->es->search( |
147 | | - index => $self->index->name, |
148 | | - type => 'favorite', |
149 | | - body => { |
150 | | - size => $size, |
151 | | - from => ( $page - 1 ) * $size, |
152 | | - query => { match_all => {} }, |
153 | | - sort => [ { 'date' => { order => 'desc' } } ] |
154 | | - } |
155 | | - ); |
156 | | - return {} unless $favs->{hits}{total}; |
157 | | - |
158 | | - my @favs = map { $_->{_source} } @{ $favs->{hits}{hits} }; |
159 | | - |
160 | | - return +{ |
161 | | - favorites => \@favs, |
162 | | - took => $favs->{took}, |
163 | | - total => $favs->{total} |
164 | | - }; |
165 | | -} |
| 7 | +extends 'ElasticSearchX::Model::Document::Set'; |
166 | 8 |
|
167 | | -sub leaderboard { |
| 9 | +has query_favorite => ( |
| 10 | + is => 'ro', |
| 11 | + isa => 'MetaCPAN::Query::Favorite', |
| 12 | + lazy => 1, |
| 13 | + builder => '_build_query_favorite', |
| 14 | + handles => [ |
| 15 | + qw< agg_by_distributions |
| 16 | + by_user |
| 17 | + leaderboard |
| 18 | + recent |
| 19 | + users_by_distribution > |
| 20 | + ], |
| 21 | +); |
| 22 | + |
| 23 | +sub _build_query_favorite { |
168 | 24 | my $self = shift; |
169 | | - |
170 | | - my $body = { |
171 | | - size => 0, |
172 | | - query => { match_all => {} }, |
173 | | - aggregations => { |
174 | | - leaderboard => |
175 | | - { terms => { field => 'distribution', size => 600 }, }, |
176 | | - }, |
177 | | - }; |
178 | | - |
179 | | - my $ret = $self->es->search( |
180 | | - index => $self->index->name, |
181 | | - type => 'favorite', |
182 | | - body => $body, |
| 25 | + return MetaCPAN::Query::Favorite->new( |
| 26 | + es => $self->es, |
| 27 | + index_name => $self->index->name, |
183 | 28 | ); |
184 | | - |
185 | | - my @leaders |
186 | | - = @{ $ret->{aggregations}{leaderboard}{buckets} }[ 0 .. 99 ]; |
187 | | - |
188 | | - return { |
189 | | - leaderboard => \@leaders, |
190 | | - took => $ret->{took}, |
191 | | - total => $ret->{total} |
192 | | - }; |
193 | 29 | } |
194 | 30 |
|
195 | 31 | __PACKAGE__->meta->make_immutable; |
|
0 commit comments