File Coverage

blib/lib/SolarBeam/Response.pm
Criterion Covered Total %
statement 65 78 83.3
branch 17 26 65.3
condition 4 13 30.7
subroutine 8 9 88.8
pod 2 2 100.0
total 96 128 75.0


line stmt bran cond sub pod time code
1             package SolarBeam::Response;
2 3     3   837 use Mojo::Base -base;
  3         6  
  3         30  
3              
4 3     3   2033 use Data::Page;
  3         15273  
  3         20  
5 3     3   104 use Mojo::JSON 'decode_json';
  3         6  
  3         163  
6 3     3   1678 use Mojo::JSON::MaybeXS;
  3         22339  
  3         134  
7 3     3   43 use Mojo::Util 'decamelize';
  3         6  
  3         421  
8              
9 3   50 3   22 use constant DEBUG => $ENV{SOLARBEAM_DEBUG} || 0;
  3         7  
  3         3595  
10              
11             has docs => sub { +[] };
12             has error => undef;
13             has facet_dates => sub { +{} };
14             has facet_fields => sub { +{} };
15             has facet_queries => sub { +{} };
16             has facet_ranges => sub { +{} };
17             has num_found => 0;
18             has pager => sub { Data::Page->new };
19             has params => sub { +{} };
20             has query_time => 0;
21             has start => 0;
22             has terms => sub { +{} };
23              
24             sub facet_fields_as_hashes {
25 0     0 1 0 my $self = shift;
26              
27 0   0     0 return $self->{facet_fields_as_hashes} ||= do {
28 0         0 my $facet_fields = $self->facet_fields;
29 0         0 my %res;
30 0         0 for my $k (keys %$facet_fields) {
31 0 0       0 $res{$k} = {map { @$_{qw(value count)} } @{$facet_fields->{$k} || []}};
  0         0  
  0         0  
32             }
33 0         0 return \%res;
34             };
35             }
36              
37             sub parse {
38 9     9 1 9050 my ($self, $tx) = @_;
39 9         25 my $res = $tx->res;
40 9   100     68 my $data = $res->json || {};
41 9         1015 my $header = $data->{responseHeader};
42 9         13 my $response = $data->{response};
43 9         11 my $facets = $data->{facet_counts};
44 9         16 my $terms = $data->{terms};
45 9         13 my $field;
46              
47 9 50       27 if ($data->{error}) {
48 0   0     0 $self->error({code => $data->{error}{code} || $tx->res->code, message => $data->{error}{msg}});
49 0         0 return $self;
50             }
51              
52 9 100       24 if (!$header) {
53 4         27 my $dom = $res->dom;
54 4 50       59098 my $title = $dom->at('title') if $dom;
55              
56 4 100       1602 if ($title) {
57 2         24 $self->error({message => $title->text});
58             }
59             else {
60 2         13 $self->error({code => $res->code, message => $res->body});
61             }
62 4         229 return $self;
63             }
64              
65 5 50       24 if ($tx->error) {
66 0         0 $self->error($tx->error);
67 0         0 return $self;
68             }
69              
70 5         159 for $field (keys %$header) {
71 14         46 my $method = decamelize ucfirst $field;
72 14 100       245 $self->$method($header->{$field}) if $self->can($method);
73             }
74              
75 5         29 for $field (keys %$response) {
76 13         67 my $method = decamelize ucfirst $field;
77 13 100       181 $self->$method($response->{$field}) if $self->can($method);
78             }
79              
80 5         20 for $field (keys %$facets) {
81 8 50       47 $self->$field($facets->{$field}) if $self->can($field);
82             }
83              
84 5         18 my $ff = $self->facet_fields;
85 5 50       16 if ($ff) {
86 5         9 for $field (keys %$ff) {
87 1         3 $ff->{$field} = $self->_build_count_list($ff->{$field});
88             }
89             }
90              
91 5 50       11 if ($self->facet_ranges) {
92 5         12 for $field (keys %{$self->facet_ranges}) {
  5         10  
93 1         6 my $range = $self->facet_ranges->{$field};
94 1         5 $range->{counts} = $self->_build_count_list($range->{counts});
95             }
96             }
97              
98 5 100       24 if ($terms) {
99 1         2 my $sane_terms = {};
100 1         3 for $field (keys %$terms) {
101 2         6 $sane_terms->{$field} = $self->_build_count_list($terms->{$field});
102             }
103 1         4 $self->terms($sane_terms);
104             }
105              
106 5 50 33     32 if (!$self->error && $response) {
107 5         48 $self->pager->total_entries($self->num_found);
108             }
109              
110 5         308 $self;
111             }
112              
113             sub _build_count_list {
114 4     4   5 my ($self, $list) = @_;
115 4         4 my @result = ();
116 4         13 for (my $i = 1; $i < @$list; $i += 2) {
117 130         390 push @result, {value => $list->[$i - 1], count => $list->[$i]};
118             }
119 4         21 return \@result;
120             }
121              
122             1;
123              
124             =encoding utf8
125              
126             =head1 NAME
127              
128             SolarBeam::Response - Represents a Solr search response
129              
130             =head1 SYNOPSIS
131              
132             use SolarBeam::Response;
133             my $tx = Mojo::UserAgent->new->post($solr_url, form => \%query);
134             my $res = SolarBeam::Response->new->parse($tx);
135              
136             if ($res->error) {
137             die sprintf "%s: %s", $res->error->{code} || 0, $res->error->{message};
138             }
139              
140             for my $doc (@{$res->docs}) {
141             say $doc->{surname};
142             }
143              
144             =head1 DESCRIPTION
145              
146             L holds the response from L or
147             L.
148              
149             =head1 ATTRIBUTES
150              
151             =head2 docs
152              
153             $array_ref = $self->docs;
154             $self = $self->docs([{}, ...]);
155              
156             Holds a list of the documents retrieved from Solr.
157              
158             =head2 error
159              
160             $hash_ref = $self->error;
161             $self = $self->error({message => "Error message", code => 500});
162              
163             Holds either a hash-ref with error details or C if no error is
164             detected. This attribute is modeled the same way as L,
165             but can also contain detailed error messages from the Solr server.
166              
167             =head2 facet_dates
168              
169             $hash_ref = $self->facet_dates;
170              
171             TODO.
172              
173             =head2 facet_fields
174              
175             $hash_ref = $self->facet_fields;
176              
177             TODO.
178              
179             =head2 facet_queries
180              
181             $hash_ref = $self->facet_queries;
182              
183             TODO.
184              
185             =head2 facet_ranges
186              
187             $hash_ref = $self->facet_ranges;
188              
189             TODO.
190              
191             =head2 num_found
192              
193             $int = $self->num_found;
194              
195             Holds the number of matching documents. This number can be higher than the
196             number of elements in L.
197              
198             =head2 pager
199              
200             $pager = $self->pager;
201             $self = $self->pager(Data::Page->new);
202              
203             Holds a L object.
204              
205             =head2 params
206              
207             $hash_ref = $self->params;
208              
209             Holds the search params sent to Solr.
210              
211             =head2 query_time
212              
213             $int = $self->query_time;
214              
215             The time the search took.
216              
217             =head2 start
218              
219             $int = $self->start;
220              
221             Offset of the search result.
222              
223             =head2 terms
224              
225             $hash_ref = $self->terms;
226              
227             TODO
228              
229             =head1 METHODS
230              
231             =head2 facet_fields_as_hashes
232              
233             $hash_ref = $self->facet_fields_as_hashes;
234              
235             Turns the arrays in L into hashes instead. Example:
236              
237             $self->facet_fields = {colors => [{value => "red", count => 42}]};
238             $self->facet_fields_as_hashes = {colors => {red => 42}}
239              
240             =head2 parse
241              
242             $self = $self->parse(Mojo::Transaction->new);
243              
244             Used to parse the result from a query. Will populate the different
245             L.
246              
247             =head1 SEE ALSO
248              
249             L.
250              
251             =cut