|
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