—package
SolarBeam::Response;
use
Mojo::Base -base;
use
Data::Page;
use
Mojo::JSON::MaybeXS;
has
docs
=>
sub
{ +[] };
has
error
=>
undef
;
has
facet_dates
=>
sub
{ +{} };
has
facet_fields
=>
sub
{ +{} };
has
facet_queries
=>
sub
{ +{} };
has
facet_ranges
=>
sub
{ +{} };
has
num_found
=> 0;
has
pager
=>
sub
{ Data::Page->new };
has
params
=>
sub
{ +{} };
has
query_time
=> 0;
has
start
=> 0;
has
terms
=>
sub
{ +{} };
has
'tx'
;
sub
facet_fields_as_hashes {
my
$self
=
shift
;
return
$self
->{facet_fields_as_hashes} ||=
do
{
my
$facet_fields
=
$self
->facet_fields;
my
%res
;
for
my
$k
(
keys
%$facet_fields
) {
$res
{
$k
} = {
map
{
@$_
{
qw(value count)
} } @{
$facet_fields
->{
$k
} || []}};
}
return
\
%res
;
};
}
sub
parse {
my
(
$self
,
$tx
) =
@_
;
my
$res
=
$tx
->res;
my
$data
=
$res
->json || {};
my
$header
=
$data
->{responseHeader};
my
$response
=
$data
->{response};
my
$facets
=
$data
->{facet_counts};
my
$terms
=
$data
->{terms};
my
$field
;
$self
->tx(
$tx
);
if
(
$data
->{error}) {
$self
->error({
code
=>
$data
->{error}{code} ||
$tx
->res->code,
message
=>
$data
->{error}{msg}});
return
$self
;
}
if
(
$res
->code and !
$header
) {
my
$dom
=
$res
->dom;
if
(
$dom
and
$dom
->at(
'title'
)) {
$self
->error({
code
=>
$res
->code,
message
=>
$dom
->at(
'title'
)->text});
}
else
{
$self
->error({
code
=>
$res
->code,
message
=>
$res
->body ||
'Missing response headers.'
});
}
return
$self
;
}
if
(
$tx
->error) {
$tx
->error->{message} ||=
'Unknown error'
;
$self
->error(
$tx
->error);
return
$self
;
}
for
$field
(
keys
%$header
) {
my
$method
= decamelize
ucfirst
$field
;
$self
->
$method
(
$header
->{
$field
})
if
$self
->can(
$method
);
}
for
$field
(
keys
%$response
) {
my
$method
= decamelize
ucfirst
$field
;
$self
->
$method
(
$response
->{
$field
})
if
$self
->can(
$method
);
}
for
$field
(
keys
%$facets
) {
$self
->
$field
(
$facets
->{
$field
})
if
$self
->can(
$field
);
}
my
$ff
=
$self
->facet_fields;
if
(
$ff
) {
for
$field
(
keys
%$ff
) {
$ff
->{
$field
} =
$self
->_build_count_list(
$ff
->{
$field
});
}
}
if
(
$self
->facet_ranges) {
for
$field
(
keys
%{
$self
->facet_ranges}) {
my
$range
=
$self
->facet_ranges->{
$field
};
$range
->{counts} =
$self
->_build_count_list(
$range
->{counts});
}
}
if
(
$terms
) {
my
$sane_terms
= {};
for
$field
(
keys
%$terms
) {
$sane_terms
->{
$field
} =
$self
->_build_count_list(
$terms
->{
$field
});
}
$self
->terms(
$sane_terms
);
}
if
(!
$self
->error &&
$response
) {
$self
->pager->total_entries(
$self
->num_found);
}
$self
;
}
sub
_build_count_list {
my
(
$self
,
$list
) =
@_
;
my
@result
= ();
for
(
my
$i
= 1;
$i
<
@$list
;
$i
+= 2) {
push
@result
, {
value
=>
$list
->[
$i
- 1],
count
=>
$list
->[
$i
]};
}
return
\
@result
;
}
1;
=encoding utf8
=head1 NAME
SolarBeam::Response - Represents a Solr search response
=head1 SYNOPSIS
use SolarBeam::Response;
my $tx = Mojo::UserAgent->new->post($solr_url, form => \%query);
my $res = SolarBeam::Response->new->parse($tx);
if ($res->error) {
die sprintf "%s: %s", $res->error->{code} || 0, $res->error->{message};
}
for my $doc (@{$res->docs}) {
say $doc->{surname};
}
=head1 DESCRIPTION
L<SolarBeam::Response> holds the response from L<SolarBeam/autocomplete> or
L<SolarBeam/search>.
=head1 ATTRIBUTES
=head2 docs
$array_ref = $self->docs;
$self = $self->docs([{}, ...]);
Holds a list of the documents retrieved from Solr.
=head2 error
$hash_ref = $self->error;
$self = $self->error({message => "Error message", code => 500});
Holds either a hash-ref with error details or C<undef()> if no error is
detected. This attribute is modeled the same way as L<Mojo::Transaction/error>,
but can also contain detailed error messages from the Solr server.
=head2 facet_dates
$hash_ref = $self->facet_dates;
TODO.
=head2 facet_fields
$hash_ref = $self->facet_fields;
TODO.
=head2 facet_queries
$hash_ref = $self->facet_queries;
TODO.
=head2 facet_ranges
$hash_ref = $self->facet_ranges;
TODO.
=head2 num_found
$int = $self->num_found;
Holds the number of matching documents. This number can be higher than the
number of elements in L</docs>.
=head2 pager
$pager = $self->pager;
$self = $self->pager(Data::Page->new);
Holds a L<Data::Page> object.
=head2 params
$hash_ref = $self->params;
Holds the search params sent to Solr.
=head2 query_time
$int = $self->query_time;
The time the search took.
=head2 start
$int = $self->start;
Offset of the search result.
=head2 terms
$hash_ref = $self->terms;
=head2 tx
last tx passed to parse
TODO
=head1 METHODS
=head2 facet_fields_as_hashes
$hash_ref = $self->facet_fields_as_hashes;
Turns the arrays in L</facet_fields> into hashes instead. Example:
$self->facet_fields = {colors => [{value => "red", count => 42}]};
$self->facet_fields_as_hashes = {colors => {red => 42}}
=head2 parse
$self = $self->parse(Mojo::Transaction->new);
Used to parse the result from a query. Will populate the different
L</ATTRIBUTES>.
=head1 SEE ALSO
L<SolarBeam>.
=cut