%PDF- %PDF-
Direktori : /home/opti/optisoftcom-new/perl5/lib/perl5/MongoDB/ |
Current File : /home/opti/optisoftcom-new/perl5/lib/perl5/MongoDB/QueryResult.pm |
# Copyright 2014 - present MongoDB, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. use strict; use warnings; package MongoDB::QueryResult; # ABSTRACT: An iterator for Mongo query results use version; our $VERSION = 'v2.0.2'; use Moo; use MongoDB::Error; use MongoDB::_Constants; use MongoDB::Op::_GetMore; use MongoDB::Op::_KillCursors; use MongoDB::_Types qw( BSONCodec ClientSession HostAddress Intish Numish Stringish ); use Types::Standard qw( Maybe ArrayRef Any InstanceOf HashRef Overload ); use namespace::clean; with $_ for qw( MongoDB::Role::_PrivateConstructor MongoDB::Role::_CursorAPI ); # attributes needed for get more has _client => ( is => 'rw', required => 1, isa => InstanceOf['MongoDB::MongoClient'], ); has _address => ( is => 'ro', required => 1, isa => HostAddress, ); has _full_name => ( is => 'ro', required => 1, isa => Stringish ); has _bson_codec => ( is => 'ro', required => 1, isa => BSONCodec, ); has _batch_size => ( is => 'ro', required => 1, isa => Intish, ); has _max_time_ms => ( is => 'ro', isa => Numish, ); has _session => ( is => 'rwp', isa => Maybe[ClientSession], ); # attributes for tracking progress has _cursor_at => ( is => 'ro', required => 1, isa => Numish, ); sub _inc_cursor_at { $_[0]{_cursor_at}++ } has _limit => ( is => 'ro', required => 1, isa => Numish, ); # attributes from actual results # integer or MongoDB::_CursorID or Math::BigInt has _cursor_id => ( is => 'ro', required => 1, writer => '_set_cursor_id', isa => Any, ); has _cursor_start => ( is => 'ro', required => 1, writer => '_set_cursor_start', isa => Numish, ); has _cursor_flags => ( is => 'ro', required => 1, writer => '_set_cursor_flags', isa => HashRef, ); has _cursor_num => ( is => 'ro', required => 1, isa => Numish, ); sub _inc_cursor_num { $_[0]{_cursor_num} += $_[1] } has _docs => ( is => 'ro', required => 1, isa => ArrayRef, ); sub _drained { ! @{$_[0]{_docs}} } sub _doc_count { scalar @{$_[0]{_docs}} } sub _add_docs { my $self = shift; push @{$self->{_docs}}, @_; } sub _next_doc { shift @{$_[0]{_docs}} } sub _drain_docs { my @docs = @{$_[0]{_docs}}; $_[0]{_cursor_at} += scalar @docs; @{$_[0]{_docs}} = (); return @docs; } # for backwards compatibility sub started_iterating() { 1 } sub _info { my ($self) = @_; return { flag => $self->_cursor_flags, cursor_id => $self->_cursor_id, start => $self->_cursor_start, at => $self->_cursor_at, num => $self->_cursor_num, }; } #pod =method has_next #pod #pod if ( $response->has_next ) { #pod ... #pod } #pod #pod Returns true if additional documents are available. This will #pod attempt to get another batch of documents from the server if #pod necessary. #pod #pod =cut sub has_next { my ($self) = @_; my $limit = $self->_limit; if ( $limit > 0 && ( $self->_cursor_at + 1 ) > $limit ) { $self->_kill_cursor; return 0; } return !$self->_drained || $self->_get_more; } #pod =method next #pod #pod while ( $doc = $result->next ) { #pod process_doc($doc) #pod } #pod #pod Returns the next document or C<undef> if the server cursor is exhausted. #pod #pod =cut sub next { my ($self) = @_; return unless $self->has_next; $self->_inc_cursor_at(); return $self->_next_doc; } #pod =method batch #pod #pod while ( @batch = $result->batch ) { #pod for $doc ( @batch ) { #pod process_doc($doc); #pod } #pod } #pod #pod Returns the next batch of documents or an empty list if the server cursor is exhausted. #pod #pod =cut sub batch { my ($self) = @_; return unless $self->has_next; return $self->_drain_docs; } sub _get_more { my ($self) = @_; return 0 if $self->_cursor_id == 0; my $limit = $self->_limit; my $want = $limit > 0 ? ( $limit - $self->_cursor_at ) : $self->_batch_size; my ($db_name, $coll_name) = split(/\./, $self->_full_name, 2); my $op = MongoDB::Op::_GetMore->_new( full_name => $self->_full_name, db_name => $db_name, coll_name => $coll_name, client => $self->_client, bson_codec => $self->_bson_codec, cursor_id => $self->_cursor_id, batch_size => $want, ( $self->_max_time_ms ? ( max_time_ms => $self->_max_time_ms ) : () ), session => $self->_session, monitoring_callback => $self->_client->monitoring_callback, ); my $result = $self->_client->send_direct_op( $op, $self->_address ); $self->_set_cursor_id( $result->{cursor_id} ); $self->_set_cursor_flags( $result->{flags} ); $self->_set_cursor_start( $result->{starting_from} ); $self->_inc_cursor_num( $result->{number_returned} ); $self->_add_docs( @{ $result->{docs} } ); return scalar @{ $result->{docs} }; } #pod =method all #pod #pod @docs = $result->all; #pod #pod Returns all documents as a list. #pod #pod =cut sub all { my ($self) = @_; my @ret; push @ret, $self->_drain_docs while $self->has_next; return @ret; } sub _kill_cursor { my ($self) = @_; my $cursor_id = $self->_cursor_id; return if !defined $cursor_id || $cursor_id == 0; my ($db_name, $coll_name) = split(/\./, $self->_full_name, 2); my $op = MongoDB::Op::_KillCursors->_new( db_name => $db_name, coll_name => $coll_name, full_name => $self->_full_name, bson_codec => $self->_bson_codec, cursor_ids => [$cursor_id], client => $self->_client, session => $self->_session, monitoring_callback => $self->_client->monitoring_callback, ); $self->_client->send_direct_op( $op, $self->_address ); $self->_set_cursor_id(0); } sub DEMOLISH { my ($self) = @_; $self->_kill_cursor; } #pod =head1 SYNOPSIS #pod #pod $cursor = $coll->find( $filter ); #pod $result = $cursor->result; #pod #pod while ( $doc = $result->next ) { #pod process_doc($doc) #pod } #pod #pod =head1 DESCRIPTION #pod #pod This class defines an iterator against a query result. It automatically #pod fetches additional results from the originating mongod/mongos server #pod on demand. #pod #pod For backwards compatibility reasons, L<MongoDB::Cursor> encapsulates query #pod parameters and generates a C<MongoDB::QueryResult> object on demand. All #pod iterators on C<MongoDB::Cursor> delegate to C<MongoDB::QueryResult> object. #pod #pod Retrieving this object and iterating on it directly will be slightly #pod more efficient. #pod #pod =head1 USAGE #pod #pod =head2 Error handling #pod #pod Unless otherwise explicitly documented, all methods throw exceptions if #pod an error occurs. The error types are documented in L<MongoDB::Error>. #pod #pod To catch and handle errors, the L<Try::Tiny> and L<Safe::Isa> modules #pod are recommended: #pod #pod =head2 Cursor destruction #pod #pod When a C<MongoDB::QueryResult> object is destroyed, a cursor termination #pod request will be sent to the originating server to free server resources. #pod #pod =head2 Multithreading #pod #pod Iterators are cloned in threads, but not reset. Iterating from multiple #pod threads will give unpredictable results. Only iterate from a single #pod thread. #pod #pod =cut 1; __END__ =pod =encoding UTF-8 =head1 NAME MongoDB::QueryResult - An iterator for Mongo query results =head1 VERSION version v2.0.2 =head1 SYNOPSIS $cursor = $coll->find( $filter ); $result = $cursor->result; while ( $doc = $result->next ) { process_doc($doc) } =head1 DESCRIPTION This class defines an iterator against a query result. It automatically fetches additional results from the originating mongod/mongos server on demand. For backwards compatibility reasons, L<MongoDB::Cursor> encapsulates query parameters and generates a C<MongoDB::QueryResult> object on demand. All iterators on C<MongoDB::Cursor> delegate to C<MongoDB::QueryResult> object. Retrieving this object and iterating on it directly will be slightly more efficient. =head1 USAGE =head2 Error handling Unless otherwise explicitly documented, all methods throw exceptions if an error occurs. The error types are documented in L<MongoDB::Error>. To catch and handle errors, the L<Try::Tiny> and L<Safe::Isa> modules are recommended: =head2 Cursor destruction When a C<MongoDB::QueryResult> object is destroyed, a cursor termination request will be sent to the originating server to free server resources. =head2 Multithreading Iterators are cloned in threads, but not reset. Iterating from multiple threads will give unpredictable results. Only iterate from a single thread. =head1 METHODS =head2 has_next if ( $response->has_next ) { ... } Returns true if additional documents are available. This will attempt to get another batch of documents from the server if necessary. =head2 next while ( $doc = $result->next ) { process_doc($doc) } Returns the next document or C<undef> if the server cursor is exhausted. =head2 batch while ( @batch = $result->batch ) { for $doc ( @batch ) { process_doc($doc); } } Returns the next batch of documents or an empty list if the server cursor is exhausted. =head2 all @docs = $result->all; Returns all documents as a list. =head1 AUTHORS =over 4 =item * David Golden <david@mongodb.com> =item * Rassi <rassi@mongodb.com> =item * Mike Friedman <friedo@friedo.com> =item * Kristina Chodorow <k.chodorow@gmail.com> =item * Florian Ragwitz <rafl@debian.org> =back =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2018 by MongoDB, Inc. This is free software, licensed under: The Apache License, Version 2.0, January 2004 =cut