package Search::Elasticsearch::Compat::ScrolledSearch; $Search::Elasticsearch::Compat::ScrolledSearch::VERSION = '0.10'; use strict; use warnings FATAL => 'all', NONFATAL => 'redefine'; use Search::Elasticsearch::Util qw(parse_params); # ABSTRACT: A wrapper for managing scrolled searches #=================================== sub new { #=================================== my $class = shift; my ( $es, $params ) = parse_params(@_); my $scroll = $params->{scroll} ||= '1m'; my $method = $params->{q} ? 'searchqs' : 'search'; my $as_json = delete $params->{as_json}; my $results = $es->$method($params); my $self = { _es => $es, _scroll_id => $results->{_scroll_id}, _scroll => $scroll, _total => $results->{hits}{total}, _buffer => $results->{hits}{hits}, _max_score => $results->{hits}{max_score}, _facets => $results->{facets}, _eof => 0, _as_json => $as_json, }; return bless( $self, $class ); } #=================================== sub next { #=================================== my $self = shift; my $size = shift || 1; while ( @{ $self->{_buffer} } < $size && !$self->{_eof} ) { $self->refill_buffer; } my @results = splice @{ $self->{_buffer} }, 0, $size; return $self->{_as_json} ? $self->{_es}->JSON->encode( \@results ) : $size == 1 ? $results[0] : @results; } #=================================== sub drain_buffer { #=================================== my $self = shift; if ( my $size = @{ $self->{_buffer} } ) { return $self->next($size); } return $self->{_as_json} ? '[]' : (); } #=================================== sub refill_buffer { #=================================== my $self = shift; unless ( $self->{_eof} ) { my $results = $self->{_es}->scroll( scroll => $self->{_scroll}, scroll_id => $self->{_scroll_id} ); my @hits = @{ $results->{hits}{hits} }; $self->{_eof}++ if @hits == 0; $self->{_scroll_id} = $results->{_scroll_id}; push @{ $self->{_buffer} }, @hits; } return scalar @{ $self->{_buffer} }; } #=================================== sub total { shift->{_total} } sub max_score { shift->{_max_score} } sub eof { shift->{_eof} } #=================================== #=================================== sub facets { #=================================== my $self = shift; return $self->{_as_json} ? $self->{_es}->JSON->encode( $self->{_facets} || {} ) : $self->{_facets} } 1 __END__ =pod =encoding UTF-8 =head1 NAME Search::Elasticsearch::Compat::ScrolledSearch - A wrapper for managing scrolled searches =head1 VERSION version 0.10 =head1 SYNOPSIS $scroller = $es->scrolled_search($search_params); OR $scroller = Search::Elasticsearch::Compat::ScrolledSearch($es,$search_params); while (my $result = $scroller->next) { # do something } $total = $scroller->total; $bool = $scroller->eof $score = $scroller->max_score; $facets = $scroller->facets; =head1 DESCRIPTION C is a convenience iterator for scrolled searches. It accepts the standard search parameters that would be passed to L. The C parameter defaults to C<1m>. $scroller = $es->scrolled_search( query => {match_all=>{}}, scroll => '5m' # keep the scroll request # live for 5 minutes ); =head1 METHODS =head2 C $scroller = $es->scrolled_search($search_params); OR $scroller = Search::Elasticsearch::Compat::ScrolledSearch($es,$search_params); =head2 next() @results = $scroller->next() @results = $scroller->next($no_of_results); Returns the next result, or the next C<$no_of_results> or an empty list when no more results are available. An error is thrown if the C has already expired. If C<< as_json => 1 >> is specified, then L will always return a JSON array: $scroller->next() # '[{...}]' $scroller->next(2) # '[{...},{...}]' # if no results left: '[]' =head2 drain_buffer() @docs = $scroller->drain_buffer; Returns and removes all docs that are currently stored in the buffer. =head2 refill_buffer() $buffer_size = $scroller->refill_buffer Pulls the next set of results from Elasticsearch (if any) and returns the total number of docs stored in the internal buffer. =head2 total() $total = $scroller->total The total number of hits =head2 max_score() $score = $scroller->max_score The C returned from the first search request (if available). =head2 eof() $bool = $scroller->eof Returns C if no more results are available. Note: if no results match the search, then C could be C but the first call to C will return zero results. =head2 facets() $facets = $scroller->facets The C returned from the first search request (if any). If C<< as_json => 1 >> is specified, then L will always return a JSON object. =head1 SEE ALSO L, L and L =head1 AUTHOR Clinton Gormley =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2014 by Elasticsearch BV. This is free software, licensed under: The Apache License, Version 2.0, January 2004 =cut