<commit_before>package Net::CouchDB::ViewResult;
use warnings;
use strict;

use Net::CouchDB;
use Net::CouchDB::Request;
use Net::CouchDB::ViewResultRow;
use URI;

sub new {
    my $class = shift;
    my $args  = shift;
    my $json = Net::CouchDB->json;

    my %params = %$args;

    # searches by key
    if ( my $key = delete $params{key} ) {
        $key = $json->encode($key);
        $params{startkey} = $params{endkey} = $key;
    }

    my $self = bless {
        view   => delete $params{view},
        params => \%params,
    }, $class;
    return $self;
}

sub view   { shift->{view}   }
sub params { shift->{params} }

sub count {
    my ($self) = @_;
    my $rows = $self->response->content->{rows};
    return scalar @$rows;
}

sub total_rows {
    my ($self) = @_;
    return $self->response->content->{total_rows};
}

sub first {
    my ($self) = @_;
    return if $self->count < 1;
    return Net::CouchDB::ViewResultRow->new({
        result => $self,
        row    => $self->response->content->{rows}[0],
    });
}

sub response {
    my ($self) = @_;
    return $self->{response} if exists $self->{response};
    my $res = $self->request( 'GET', {
        description => 'retrieve the view',
        200         => 'ok',
        params      => $self->params,
    });
    return $self->{response} = $res;
}

# use the design document's ua
sub ua { shift->view->design->ua }

sub uri { shift->view->uri }

1;

__END__

=head1 NAME

Net::CouchDB::ViewResult - the result of searching a view

=head1 SYNOPSIS

    my $rs = $view->search({ key => 'foo' });
    printf "There are %d rows\n", $rs->count;

    my $rs = $view->search({ count => 20, startkey_docid => 'abc' });
    my $doc = $rs->first;

=head1 DESCRIPTION

A L<Net::CouchDB::ViewResult> object represents the results of searching a
specific view.  Those results may be all rows from the view or it may be a
subset of those rows.  In general, a newly created ViewResult object lazily
represents the search results and does not actually query the CouchDB instance
until absolutely necessary.  The query usually happens the first time a
method is called on the ViewResult object.

=head1 METHODS

=head2 new

This method is only intended to be used internally.  The correct way to create
a new ViewResult object is to call L<Net::CouchDB::View/search>.

=head2 count

Returns the number of rows in the result.  This number will be less than
or equal to the number returned by L</total_rows>.

=head2 first

Returns a L<Net::CouchDB::ViewResultRow> object representing the first
row in the result.  If there are no rows in the result, it returns
C<undef>.

=head2 search

This method is the workhorse of L<Net::CouchDB::ViewResult>.  It refines the<commit_msg>Add a few lines of documentation for the next method<commit_after>package Net::CouchDB::ViewResult;
use warnings;
use strict;

use Net::CouchDB;
use Net::CouchDB::Request;
use Net::CouchDB::ViewResultRow;
use URI;

sub new {
    my $class = shift;
    my $args  = shift;
    my $json = Net::CouchDB->json;

    my %params = %$args;

    # searches by key
    if ( my $key = delete $params{key} ) {
        $key = $json->encode($key);
        $params{startkey} = $params{endkey} = $key;
    }

    my $self = bless {
        view   => delete $params{view},
        params => \%params,
    }, $class;

    # Note that this doesn't actually fetch the result; it only 
    # sets up the container for the result.
    # Fetching the data is done on demand ... (for better or worse)

    return $self;
}

sub view   { shift->{view}   }
sub params { shift->{params} }

sub count {
    my ($self) = @_;
    my $rows = $self->response->content->{rows};
    return scalar @$rows;
}

sub total_rows {
    my ($self) = @_;
    return $self->response->content->{total_rows};
}

sub first {
    my ($self) = @_;
    return if $self->count < 1;
    return Net::CouchDB::ViewResultRow->new({
        result => $self,
        row    => $self->response->content->{rows}[0],
    });
}

sub response {
    my ($self) = @_;
    return $self->{response} if exists $self->{response};
    my $res = $self->request( 'GET', {
        description => 'retrieve the view',
        200         => 'ok',
        params      => $self->params,
    });
    return $self->{response} = $res;
}

# use the design document's ua
sub ua { shift->view->design->ua }

sub uri { shift->view->uri }

1;

__END__

=head1 NAME

Net::CouchDB::ViewResult - the result of searching a view

=head1 SYNOPSIS

    my $rs = $view->search({ key => 'foo' });
    printf "There are %d rows\n", $rs->count;

    my $rs = $view->search({ count => 20, startkey_docid => 'abc' });
    my $doc = $rs->first;

=head1 DESCRIPTION

A L<Net::CouchDB::ViewResult> object represents the results of searching a
specific view.  Those results may be all rows from the view or it may be a
subset of those rows.  In general, a newly created ViewResult object lazily
represents the search results and does not actually query the CouchDB instance
until absolutely necessary.  The query usually happens the first time a
method is called on the ViewResult object.

=head1 METHODS

=head2 new

This method is only intended to be used internally.  The correct way to create
a new ViewResult object is to call L<Net::CouchDB::View/search>.

=head2 count

Returns the number of rows in the result.  This number will be less than
or equal to the number returned by L</total_rows>.

=head2 first

Returns a L<Net::CouchDB::ViewResultRow> object representing the first
row in the result.  If there are no rows in the result, it returns
C<undef>.

=head2 next

Returns the next L<Net::CouchDB::ViewResultRow> until there are no
more rows where it returns C<undef>.

=head2 search

This method is the workhorse of L<Net::CouchDB::ViewResult>.  It refines the
{'fraction_non_alphanumeric': 0.12857142857142856, 'fraction_numerical': 0.005679862306368331, 'mean_word_length': 3.115439093484419, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7460750', 'n_tokens_mistral': 1898, 'n_tokens_neox': 1851, 'n_words': 676}