MongoDB
view release on metacpan or search on metacpan
lib/MongoDB/Op/_Query.pm view on Meta::CPAN
if ( defined $self->{options}{collation} and !$link->supports_collation ) {
MongoDB::UsageError->throw(
"MongoDB host '" . $link->address . "' doesn't support collation" );
}
my $res =
$link->supports_query_commands
? $self->_command_query( $link, $topology )
: $self->_legacy_query( $link, $topology );
return $res;
}
sub _command_query {
my ( $self, $link, $topology ) = @_;
my $op = MongoDB::Op::_Command->_new(
db_name => $self->db_name,
query => $self->_as_command,
query_flags => {},
read_preference => $self->read_preference,
bson_codec => $self->bson_codec,
session => $self->session,
monitoring_callback => $self->monitoring_callback,
);
my $res = $op->execute( $link, $topology );
return $self->_build_result_from_cursor($res);
}
sub _legacy_query {
my ( $self, $link, $topology ) = @_;
my $opts = $self->{options};
my $query_flags = {
tailable => ( $opts->{cursorType} =~ /^tailable/ ? 1 : 0 ),
await_data => $opts->{cursorType} eq 'tailable_await',
immortal => $opts->{noCursorTimeout},
partial => $opts->{allowPartialResults},
};
my $query = $self->_as_query_document($opts);
my $full_name = $self->full_name;
# rules for calculating initial batch size
my $limit = $opts->{limit} // 0;
my $batch_size = $opts->{batchSize} // 0;
my $n_to_return =
$limit == 0 ? $batch_size
: $batch_size == 0 ? $limit
: $limit < 0 ? $limit
: min( $limit, $batch_size );
my $proj =
$opts->{projection} ? $self->bson_codec->encode_one( $opts->{projection} ) : undef;
# $query is passed as a reference because it *may* be replaced
$self->_apply_op_query_read_prefs( $link, $topology, $query_flags, \$query );
my $filter = $self->bson_codec->encode_one($query);
my ( $op_bson, $request_id ) =
MongoDB::_Protocol::write_query( $full_name, $filter, $proj, $opts->{skip},
$n_to_return, $query_flags );
my $result =
$self->_query_and_receive( $link, $op_bson, $request_id, $self->bson_codec );
my $class =
$self->has_post_filter ? "MongoDB::QueryResult::Filtered" : "MongoDB::QueryResult";
return $class->_new(
_client => $self->client,
_address => $link->address,
_full_name => $full_name,
_bson_codec => $self->bson_codec,
_batch_size => $n_to_return,
_cursor_at => 0,
_limit => $limit,
_cursor_id => $result->{cursor_id},
_cursor_start => $result->{starting_from},
_cursor_flags => $result->{flags} || {},
_cursor_num => $result->{number_returned},
_docs => $result->{docs},
_post_filter => $self->post_filter,
);
}
# awful hack: avoid calling into boolean to get true/false
my $TRUE = boolean::true();
my $FALSE = boolean::false();
sub _as_query_document {
my ($self, $opts) = @_;
# Reconstruct query modifiers style from options. However, we only
# apply $maxTimeMS if we're not running a command via OP_QUERY against
# the '$cmd' collection. For commands, we expect maxTimeMS to be in
# the command itself.
my $query = {
( defined $opts->{comment} ? ( '$comment' => $opts->{comment} ) : () ),
( defined $opts->{hint} ? ( '$hint' => $opts->{hint} ) : () ),
( defined $opts->{max} ? ( '$max' => $opts->{max} ) : () ),
( defined $opts->{min} ? ( '$min' => $opts->{min} ) : () ),
( defined $opts->{sort} ? ( '$orderby' => $opts->{sort} ) : () ),
( defined $opts->{maxScan} ? ( '$maxScan' => $opts->{maxScan} ) : () ),
( defined $opts->{returnKey} ? ( '$returnKey' => $opts->{returnKey} ) : () ),
( defined $opts->{showRecordId} ? ( '$showDiskLoc' => $opts->{showRecordId} ) : () ),
( defined $opts->{snapshot} ? ( '$snapshot' => $opts->{snapshot} ) : () ),
(
( defined $opts->{maxTimeMS} && $self->coll_name !~ /\A\$cmd/ )
? ( '$maxTimeMS' => $opts->{maxTimeMS} )
: ()
),
# Not a user-provided option: this is only set by MongoDB::Op::_Explain
# for legacy $explain support
( defined $opts->{explain} ? ( '$explain' => $TRUE ) : () ),
( '$query' => ( $self->filter || {} ) ),
( run in 0.492 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )