File Coverage

blib/lib/Mango/Cursor/Query.pm
Criterion Covered Total %
statement 6 68 8.8
branch 0 40 0.0
condition n/a
subroutine 2 12 16.6
pod 5 5 100.0
total 13 125 10.4


line stmt bran cond sub pod time code
1             package Mango::Cursor::Query;
2 9     9   61 use Mojo::Base 'Mango::Cursor';
  9         23  
  9         248  
3              
4 9     9   1246 use Mango::BSON 'bson_doc';
  9         59  
  9         9045  
5              
6             has [
7             qw(await_data comment hint max_scan max_time_ms read_preference snapshot),
8             qw(sort tailable)
9             ];
10             has [qw(fields query)];
11             has skip => 0;
12              
13             sub build_query {
14 0     0 1   my ($self, $explain) = @_;
15              
16 0           my %ext;
17 0 0         if (my $comment = $self->comment) { $ext{'$comment'} = $comment }
  0            
18 0 0         if ($explain) { $ext{'$explain'} = 1 }
  0            
19 0 0         if (my $hint = $self->hint) { $ext{'$hint'} = $hint }
  0            
20 0 0         if (my $max_scan = $self->max_scan) { $ext{'$maxScan'} = $max_scan }
  0            
21 0 0         if (my $max = $self->max_time_ms) { $ext{'$maxTimeMS'} = $max }
  0            
22 0 0         if (my $pref = $self->read_preference) { $ext{'$readPreference'} = $pref }
  0            
23 0 0         if (my $snapshot = $self->snapshot) { $ext{'$snapshot'} = 1 }
  0            
24 0 0         if (my $sort = $self->sort) { $ext{'$orderby'} = $sort }
  0            
25              
26 0           my $query = $self->query;
27 0 0         return $query unless keys %ext;
28 0 0         return bson_doc $query->{'$query'} ? %$query : ('$query' => $query), %ext;
29             }
30              
31             sub clone {
32 0     0 1   my $self = shift;
33 0           my $clone = $self->new;
34 0           $clone->$_($self->$_) for qw(await_data batch_size collection comment);
35 0           $clone->$_($self->$_) for qw(fields hint limit max_scan max_time_ms query);
36 0           $clone->$_($self->$_) for qw(read_preference skip snapshot sort tailable);
37 0           return $clone;
38             }
39              
40             sub count {
41 0     0 1   my $self = shift;
42 0 0         my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
43              
44 0           my $collection = $self->collection;
45 0           my $command = bson_doc
46             count => $collection->name,
47             query => $self->build_query,
48             skip => $self->skip,
49             limit => $self->limit;
50              
51             # Non-blocking
52             return $collection->db->command(
53             $command => sub {
54 0     0     my ($collection, $err, $doc) = @_;
55 0 0         $self->$cb($err, $doc ? $doc->{n} : 0);
56             }
57 0 0         ) if $cb;
58              
59             # Blocking
60 0           my $doc = $collection->db->command($command);
61 0 0         return $doc ? $doc->{n} : 0;
62             }
63              
64             sub distinct {
65 0     0 1   my ($self, $key) = (shift, shift);
66 0 0         my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
67              
68 0           my $collection = $self->collection;
69 0           my $command = bson_doc
70             distinct => $collection->name,
71             key => $key,
72             query => $self->build_query;
73              
74             # Blocking
75 0           my $db = $collection->db;
76 0 0         return $db->command($command)->{values} unless $cb;
77              
78             # Non-blocking
79 0     0     $db->command($command => sub { shift; $self->$cb(shift, shift->{values}) });
  0            
  0            
80             }
81              
82             sub explain {
83 0     0 1   my ($self, $cb) = @_;
84              
85             # Non-blocking
86 0           my $clone = $self->clone->query($self->build_query(1))->sort(undef);
87 0 0   0     return $clone->next(sub { shift; $self->$cb(@_) }) if $cb;
  0            
  0            
88              
89             # Blocking
90 0           return $clone->next;
91             }
92              
93             sub _start {
94 0     0     my ($self, $cb) = @_;
95              
96 0           my $collection = $self->collection;
97 0           my $name = $collection->full_name;
98 0           my $flags = {};
99 0 0         $flags->{tailable_cursor} = 1 if $self->tailable;
100 0 0         $flags->{await_data} = 1 if $self->await_data;
101 0           my @query = (
102             $name, $flags, $self->skip, $self->num_to_return, $self->build_query,
103             $self->fields
104             );
105              
106             # Non-blocking
107             return $collection->db->mango->query(
108 0     0     @query => sub { shift; $self->$cb(shift, $self->_enqueue(shift)) })
  0            
109 0 0         if $cb;
110              
111             # Blocking
112 0           return $self->_enqueue($collection->db->mango->query(@query));
113             }
114              
115             1;
116              
117             =encoding utf8
118              
119             =head1 NAME
120              
121             Mango::Cursor::Query - MongoDB query cursor
122              
123             =head1 SYNOPSIS
124              
125             use Mango::Cursor::Query;
126              
127             my $cursor = Mango::Cursor::Query->new(collection => $collection);
128             my $docs = $cursor->all;
129              
130             =head1 DESCRIPTION
131              
132             L is a container for MongoDB query cursors used by
133             L.
134              
135             =head1 ATTRIBUTES
136              
137             L inherits all attributes from L and
138             implements the following new ones.
139              
140             =head2 await_data
141              
142             my $await = $cursor->await_data;
143             $cursor = $cursor->await_data(1);
144              
145             Await data.
146              
147             =head2 comment
148              
149             my $comment = $cursor->comment;
150             $cursor = $cursor->comment('Fun query!');
151              
152             A comment to identify query.
153              
154             =head2 fields
155              
156             my $fields = $cursor->fields;
157             $cursor = $cursor->fields({foo => 1});
158              
159             Select fields from documents.
160              
161             =head2 hint
162              
163             my $hint = $cursor->hint;
164             $cursor = $cursor->hint({foo => 1});
165              
166             Force a specific index to be used.
167              
168             =head2 max_scan
169              
170             my $max = $cursor->max_scan;
171             $cursor = $cursor->max_scan(500);
172              
173             Limit the number of documents to scan.
174              
175             =head2 max_time_ms
176              
177             my $max = $cursor->max_time_ms;
178             $cursor = $cursor->max_time_ms(500);
179              
180             Timeout for query in milliseconds.
181              
182             =head2 query
183              
184             my $query = $cursor->query;
185             $cursor = $cursor->query({foo => 'bar'});
186              
187             Original query.
188              
189             =head2 read_preference
190              
191             my $pref = $cursor->read_preference;
192             $cursor = $cursor->read_preference({mode => 'SECONDARY'});
193              
194             Read preference.
195              
196             =head2 skip
197              
198             my $skip = $cursor->skip;
199             $cursor = $cursor->skip(5);
200              
201             Number of documents to skip, defaults to C<0>.
202              
203             =head2 snapshot
204              
205             my $snapshot = $cursor->snapshot;
206             $cursor = $cursor->snapshot(1);
207              
208             Use snapshot mode.
209              
210             =head2 sort
211              
212             my $sort = $cursor->sort;
213             $cursor = $cursor->sort({foo => 1});
214             $cursor = $cursor->sort(bson_doc(foo => 1, bar => -1));
215              
216             Sort documents, the order of keys matters.
217              
218             =head2 tailable
219              
220             my $tailable = $cursor->tailable;
221             $cursor = $cursor->tailable(1);
222              
223             Tailable cursor.
224              
225             =head1 METHODS
226              
227             L inherits all methods from L and
228             implements the following new ones.
229              
230             =head2 build_query
231              
232             my $query = $cursor->build_query;
233             my $query = $cursor->build_query($explain);
234              
235             Generate final query with cursor attributes.
236              
237             =head2 clone
238              
239             my $clone = $cursor->clone;
240              
241             Clone cursor.
242              
243             =head2 count
244              
245             my $count = $cursor->count;
246              
247             Count number of documents this cursor can return. You can also append a
248             callback to perform operation non-blocking.
249              
250             $cursor->count(sub {
251             my ($cursor, $err, $count) = @_;
252             ...
253             });
254             Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
255              
256             =head2 distinct
257              
258             my $values = $cursor->distinct('foo');
259              
260             Get all distinct values for key. You can also append a callback to perform
261             operation non-blocking.
262              
263             $cursor->distinct(foo => sub {
264             my ($cursor, $err, $values) = @_;
265             ...
266             });
267             Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
268              
269             =head2 explain
270              
271             my $doc = $cursor->explain;
272              
273             Provide information on the query plan. You can also append a callback to
274             perform operation non-blocking.
275              
276             $cursor->explain(sub {
277             my ($cursor, $err, $doc) = @_;
278             ...
279             });
280             Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
281              
282             =head1 SEE ALSO
283              
284             L, L, L.
285              
286             =cut