Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Aggregate |
|
| 1.0754716981132075;1.075 | ||||
Aggregate$Builder |
|
| 1.0754716981132075;1.075 |
1 | /* | |
2 | * #%L | |
3 | * Aggregate.java - mongodb-async-driver - Allanbank Consulting, Inc. | |
4 | * %% | |
5 | * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc. | |
6 | * %% | |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
8 | * you may not use this file except in compliance with the License. | |
9 | * You may obtain a copy of the License at | |
10 | * | |
11 | * http://www.apache.org/licenses/LICENSE-2.0 | |
12 | * | |
13 | * Unless required by applicable law or agreed to in writing, software | |
14 | * distributed under the License is distributed on an "AS IS" BASIS, | |
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
16 | * See the License for the specific language governing permissions and | |
17 | * limitations under the License. | |
18 | * #L% | |
19 | */ | |
20 | ||
21 | package com.allanbank.mongodb.builder; | |
22 | ||
23 | import java.util.ArrayList; | |
24 | import java.util.Arrays; | |
25 | import java.util.Collections; | |
26 | import java.util.List; | |
27 | import java.util.concurrent.TimeUnit; | |
28 | ||
29 | import com.allanbank.mongodb.MongoCollection; | |
30 | import com.allanbank.mongodb.ReadPreference; | |
31 | import com.allanbank.mongodb.Version; | |
32 | import com.allanbank.mongodb.bson.DocumentAssignable; | |
33 | import com.allanbank.mongodb.bson.Element; | |
34 | import com.allanbank.mongodb.bson.builder.ArrayBuilder; | |
35 | import com.allanbank.mongodb.bson.builder.BuilderFactory; | |
36 | import com.allanbank.mongodb.bson.builder.DocumentBuilder; | |
37 | import com.allanbank.mongodb.bson.element.ArrayElement; | |
38 | import com.allanbank.mongodb.bson.element.DocumentElement; | |
39 | import com.allanbank.mongodb.bson.element.IntegerElement; | |
40 | import com.allanbank.mongodb.builder.expression.Expression; | |
41 | import com.allanbank.mongodb.builder.expression.Expressions; | |
42 | ||
43 | /** | |
44 | * Aggregate provides support for the <tt>aggregate</tt> command supporting a | |
45 | * pipeline of commands to execute. | |
46 | * <p> | |
47 | * Instances of this class are constructed via the inner {@link Builder} class. | |
48 | * Due to the potential complexity of pipelines and the associated operators the | |
49 | * <tt>Builder</tt> is intended to be used with the various support classes | |
50 | * including the {@link Expressions} library. For example:<blockquote> | |
51 | * | |
52 | * <pre> | |
53 | * <code> | |
54 | * import static {@link AggregationGroupField#set com.allanbank.mongodb.builder.AggregationGroupField.set}; | |
55 | * import static {@link AggregationGroupId#id com.allanbank.mongodb.builder.AggregationGroupId.id}; | |
56 | * import static {@link AggregationProjectFields#includeWithoutId com.allanbank.mongodb.builder.AggregationProjectFields.includeWithoutId}; | |
57 | * import static {@link QueryBuilder#where com.allanbank.mongodb.builder.QueryBuilder.where}; | |
58 | * import static {@link Sort#asc com.allanbank.mongodb.builder.Sort.asc}; | |
59 | * import static {@link Sort#desc com.allanbank.mongodb.builder.Sort.desc}; | |
60 | * import static {@link Expressions#field com.allanbank.mongodb.builder.expression.Expressions.field}; | |
61 | * import static {@link Expressions#set com.allanbank.mongodb.builder.expression.Expressions.set}; | |
62 | * | |
63 | * DocumentBuilder b1 = BuilderFactory.start(); | |
64 | * DocumentBuilder b2 = BuilderFactory.start(); | |
65 | * Aggregate.Builder builder = new Aggregate.Builder(); | |
66 | * | |
67 | * builder.match(where("state").notEqualTo("NZ")) | |
68 | * .group(id().addField("state") | |
69 | * .addField("city"), | |
70 | * set("pop").sum("pop")) | |
71 | * .sort(asc("pop")) | |
72 | * .group(id("_id.state"), | |
73 | * set("biggestcity").last("_id.city"), | |
74 | * set("biggestpop").last("pop"), | |
75 | * set("smallestcity").first("_id.city"), | |
76 | * set("smallestpop").first("pop")) | |
77 | * .project( | |
78 | * includeWithoutId(), | |
79 | * set("state", field("_id")), | |
80 | * set("biggestCity", | |
81 | * b1.add(set("name", field("biggestcity"))).add( | |
82 | * set("pop", field("biggestpop")))), | |
83 | * set("smallestCity", | |
84 | * b2.add(set("name", field("smallestcity"))).add( | |
85 | * set("pop", field("smallestpop"))))) | |
86 | * .sort(desc("biggestCity.pop")); | |
87 | * </code> | |
88 | * </pre> | |
89 | * | |
90 | * </blockquote> | |
91 | * </p> | |
92 | * | |
93 | * | |
94 | * @see <a | |
95 | * href="http://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state">Example | |
96 | * Inspired By</a> | |
97 | * @api.yes This class is part of the driver's API. Public and protected members | |
98 | * will be deprecated for at least 1 non-bugfix release (version | |
99 | * numbers are <major>.<minor>.<bugfix>) before being | |
100 | * removed or modified. | |
101 | * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved | |
102 | */ | |
103 | public class Aggregate { | |
104 | ||
105 | /** | |
106 | * The first version of MongoDB to support the {@code $geoNear} pipeline | |
107 | * operator. | |
108 | */ | |
109 | 1 | public static final Version ALLOW_DISK_USAGE_REQUIRED_VERSION = Version |
110 | .parse("2.6"); | |
111 | ||
112 | /** | |
113 | * The first version of MongoDB to support the {@code aggregate} command | |
114 | * using a cursor. | |
115 | */ | |
116 | 1 | public static final Version CURSOR_VERSION = Version.parse("2.5.2"); |
117 | ||
118 | /** | |
119 | * The first version of MongoDB to support the {@code aggregate} command | |
120 | * with the explain option. | |
121 | */ | |
122 | 1 | public static final Version EXPLAIN_VERSION = Version.parse("2.5.3"); |
123 | ||
124 | /** | |
125 | * The first version of MongoDB to support the {@code $geoNear} pipeline | |
126 | * operator. | |
127 | */ | |
128 | 1 | public static final Version GEO_NEAR_REQUIRED_VERSION = Version.VERSION_2_4; |
129 | ||
130 | /** | |
131 | * The first version of MongoDB to support the {@code aggregate} command | |
132 | * with the ability to limit the execution time on the server. | |
133 | */ | |
134 | 1 | public static final Version MAX_TIMEOUT_VERSION = Find.MAX_TIMEOUT_VERSION; |
135 | ||
136 | /** | |
137 | * The first version of MongoDB to support the {@code $redact} pipeline | |
138 | * operator. | |
139 | */ | |
140 | 1 | public static final Version REDACT_REQUIRED_VERSION = Version |
141 | .parse("2.5.2"); | |
142 | ||
143 | /** The first version of MongoDB to support the {@code aggregate} command. */ | |
144 | 1 | public static final Version REQUIRED_VERSION = Version.parse("2.1.0"); |
145 | ||
146 | /** | |
147 | * Creates a new builder for a {@link Aggregate}. | |
148 | * | |
149 | * @return The builder to construct a {@link Aggregate}. | |
150 | */ | |
151 | public static Builder builder() { | |
152 | 6 | return new Builder(); |
153 | } | |
154 | ||
155 | /** | |
156 | * Set to true if the aggregation results should be allowed to spill to | |
157 | * disk. | |
158 | */ | |
159 | private final boolean myAllowDiskUsage; | |
160 | ||
161 | /** The number of documents to be returned in each batch of results. */ | |
162 | private final int myBatchSize; | |
163 | ||
164 | /** The total number of documents to be returned. */ | |
165 | private final int myLimit; | |
166 | ||
167 | /** The maximum amount of time to allow the command to run. */ | |
168 | private final long myMaximumTimeMilliseconds; | |
169 | ||
170 | /** The pipeline of operations to be applied. */ | |
171 | private final List<Element> myPipeline; | |
172 | ||
173 | /** The read preference to use. */ | |
174 | private final ReadPreference myReadPreference; | |
175 | ||
176 | /** The version required for the aggregation. */ | |
177 | private final Version myRequiredVersion; | |
178 | ||
179 | /** Set to true if the aggregation results should be returned as a cursor. */ | |
180 | private final boolean myUseCursor; | |
181 | ||
182 | /** | |
183 | * Creates a new Aggregation. | |
184 | * | |
185 | * @param builder | |
186 | * The builder for the Aggregation instance. | |
187 | */ | |
188 | 81 | protected Aggregate(final Builder builder) { |
189 | 81 | myPipeline = Collections.unmodifiableList(Arrays |
190 | .asList(builder.myPipeline.build())); | |
191 | 81 | myBatchSize = builder.myBatchSize; |
192 | 81 | myLimit = builder.myLimit; |
193 | 81 | myUseCursor = builder.myUseCursor; |
194 | 81 | myAllowDiskUsage = builder.myAllowDiskUsage; |
195 | 81 | myReadPreference = builder.myReadPreference; |
196 | 81 | myRequiredVersion = builder.myRequiredVersion; |
197 | 81 | myMaximumTimeMilliseconds = builder.myMaximumTimeMilliseconds; |
198 | 81 | } |
199 | ||
200 | /** | |
201 | * Returns the number of documents to be returned in each batch of results | |
202 | * by the cursor. | |
203 | * | |
204 | * @return The number of documents to be returned in each batch of results | |
205 | * by the cursor. | |
206 | */ | |
207 | public int getBatchSize() { | |
208 | 15 | return myBatchSize; |
209 | } | |
210 | ||
211 | /** | |
212 | * Returns the total number of documents to be returned by the cursor. | |
213 | * | |
214 | * @return The total number of documents to be returned the cursor. | |
215 | */ | |
216 | public int getCursorLimit() { | |
217 | 12 | return myLimit; |
218 | } | |
219 | ||
220 | /** | |
221 | * Returns the maximum amount of time to allow the command to run on the | |
222 | * Server before it is aborted. | |
223 | * | |
224 | * @return The maximum amount of time to allow the command to run on the | |
225 | * Server before it is aborted. | |
226 | * | |
227 | * @since MongoDB 2.6 | |
228 | */ | |
229 | public long getMaximumTimeMilliseconds() { | |
230 | 23 | return myMaximumTimeMilliseconds; |
231 | } | |
232 | ||
233 | /** | |
234 | * Returns the pipeline of operations to apply. | |
235 | * | |
236 | * @return The pipeline of operations to apply. | |
237 | */ | |
238 | public List<Element> getPipeline() { | |
239 | 52 | return myPipeline; |
240 | } | |
241 | ||
242 | /** | |
243 | * Returns the {@link ReadPreference} specifying which servers may be used | |
244 | * to execute the aggregation. | |
245 | * <p> | |
246 | * If <code>null</code> then the {@link MongoCollection} instance's | |
247 | * {@link ReadPreference} will be used. | |
248 | * </p> | |
249 | * | |
250 | * @return The read preference to use. | |
251 | * | |
252 | * @see MongoCollection#getReadPreference() | |
253 | */ | |
254 | public ReadPreference getReadPreference() { | |
255 | 20 | return myReadPreference; |
256 | } | |
257 | ||
258 | /** | |
259 | * Returns the version required for the aggregation. | |
260 | * | |
261 | * @return The version required for the aggregation. | |
262 | */ | |
263 | public Version getRequiredVersion() { | |
264 | 19 | return myRequiredVersion; |
265 | } | |
266 | ||
267 | /** | |
268 | * Returns true if the aggregation results should be allowed to spill to | |
269 | * disk. | |
270 | * | |
271 | * @return True if the aggregation results should be allowed to spill to | |
272 | * disk. | |
273 | */ | |
274 | public boolean isAllowDiskUsage() { | |
275 | 21 | return myAllowDiskUsage; |
276 | } | |
277 | ||
278 | /** | |
279 | * Returns true if the aggregation results should be returned as a cursor. | |
280 | * | |
281 | * @return True if the aggregation results should be returned as a cursor. | |
282 | */ | |
283 | public boolean isUseCursor() { | |
284 | 25 | return myUseCursor; |
285 | } | |
286 | ||
287 | /** | |
288 | * Builder provides the ability to construct aggregate command pipelines. | |
289 | * <p> | |
290 | * Methods are provided for all existing pipeline operators and generic | |
291 | * {@link #step} methods are provided to support future pipeline operators | |
292 | * while in development or before the driver is updated. | |
293 | * </p> | |
294 | * <p> | |
295 | * This builder is intended to be used with the various support classes | |
296 | * including the {@link Expressions} library. For example:<blockquote> | |
297 | * | |
298 | * <pre> | |
299 | * <code> | |
300 | * import static {@link AggregationGroupField#set com.allanbank.mongodb.builder.AggregationGroupField.set}; | |
301 | * import static {@link AggregationGroupId#id com.allanbank.mongodb.builder.AggregationGroupId.id}; | |
302 | * import static {@link AggregationProjectFields#includeWithoutId com.allanbank.mongodb.builder.AggregationProjectFields.includeWithoutId}; | |
303 | * import static {@link QueryBuilder#where com.allanbank.mongodb.builder.QueryBuilder.where}; | |
304 | * import static {@link Sort#asc com.allanbank.mongodb.builder.Sort.asc}; | |
305 | * import static {@link Sort#desc com.allanbank.mongodb.builder.Sort.desc}; | |
306 | * import static {@link Expressions#field com.allanbank.mongodb.builder.expression.Expressions.field}; | |
307 | * import static {@link Expressions#set com.allanbank.mongodb.builder.expression.Expressions.set}; | |
308 | * | |
309 | * DocumentBuilder b1 = BuilderFactory.start(); | |
310 | * DocumentBuilder b2 = BuilderFactory.start(); | |
311 | * Aggregation.Builder builder = new Aggregation.Builder(); | |
312 | * | |
313 | * builder.match(where("state").notEqualTo("NZ")) | |
314 | * .group(id().addField("state") | |
315 | * .addField("city"), | |
316 | * set("pop").sum("pop")) | |
317 | * .sort(asc("pop")) | |
318 | * .group(id("_id.state"), | |
319 | * set("biggestcity").last("_id.city"), | |
320 | * set("biggestpop").last("pop"), | |
321 | * set("smallestcity").first("_id.city"), | |
322 | * set("smallestpop").first("pop")) | |
323 | * .project( | |
324 | * includeWithoutId(), | |
325 | * set("state", field("_id")), | |
326 | * set("biggestCity", | |
327 | * b1.add(set("name", field("biggestcity"))).add( | |
328 | * set("pop", field("biggestpop")))), | |
329 | * set("smallestCity", | |
330 | * b2.add(set("name", field("smallestcity"))).add( | |
331 | * set("pop", field("smallestpop"))))) | |
332 | * .sort(desc("biggestCity.pop")); | |
333 | * </code> | |
334 | * </pre> | |
335 | * | |
336 | * </blockquote> | |
337 | * </p> | |
338 | * | |
339 | * @see <a | |
340 | * href="http://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state">Example | |
341 | * Inspired By</a> | |
342 | * @api.yes This class is part of the driver's API. Public and protected | |
343 | * members will be deprecated for at least 1 non-bugfix release | |
344 | * (version numbers are <major>.<minor>.<bugfix>) | |
345 | * before being removed or modified. | |
346 | * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved | |
347 | */ | |
348 | public static class Builder { | |
349 | ||
350 | /** | |
351 | * Set to true if the aggregation results should be allowed to spill to | |
352 | * disk. | |
353 | */ | |
354 | protected boolean myAllowDiskUsage; | |
355 | ||
356 | /** The number of documents to be returned in each batch of results. */ | |
357 | protected int myBatchSize; | |
358 | ||
359 | /** The total number of documents to be returned. */ | |
360 | protected int myLimit; | |
361 | ||
362 | /** The maximum amount of time to allow the command to run. */ | |
363 | protected long myMaximumTimeMilliseconds; | |
364 | ||
365 | /** The pipeline of operations to be applied. */ | |
366 | protected final ArrayBuilder myPipeline; | |
367 | ||
368 | /** The read preference to use. */ | |
369 | protected ReadPreference myReadPreference; | |
370 | ||
371 | /** | |
372 | * The version required for the aggregation. This is computed | |
373 | * automatically based on the pipeline constructed. | |
374 | */ | |
375 | protected Version myRequiredVersion; | |
376 | ||
377 | /** | |
378 | * Set to true if the aggregation results should be returned as a | |
379 | * cursor. | |
380 | */ | |
381 | protected boolean myUseCursor; | |
382 | ||
383 | /** | |
384 | * Creates a new Builder. | |
385 | */ | |
386 | 90 | public Builder() { |
387 | 90 | myPipeline = BuilderFactory.startArray(); |
388 | 90 | reset(); |
389 | 90 | } |
390 | ||
391 | /** | |
392 | * Allows the aggregation command can spill to disk. | |
393 | * <p> | |
394 | * This method delegates to {@link #allowDiskUsage(boolean) | |
395 | * allowDiskUsage(true)}. | |
396 | * </p> | |
397 | * <p> | |
398 | * This method also sets the builder to use a cursor to true. | |
399 | * </p> | |
400 | * | |
401 | * @return This builder for chaining method calls. | |
402 | */ | |
403 | public Builder allowDiskUsage() { | |
404 | 2 | return allowDiskUsage(true); |
405 | } | |
406 | ||
407 | /** | |
408 | * Sets to true if the aggregation command can spill to disk. | |
409 | * <p> | |
410 | * This method delegates to {@link #setAllowDiskUsage(boolean)}. | |
411 | * </p> | |
412 | * <p> | |
413 | * This method also sets the builder to use a cursor to true. | |
414 | * </p> | |
415 | * | |
416 | * @param allowDiskUsage | |
417 | * The new value for if the aggregation command can spill to | |
418 | * disk. | |
419 | * @return This builder for chaining method calls. | |
420 | */ | |
421 | public Builder allowDiskUsage(final boolean allowDiskUsage) { | |
422 | 2 | return setAllowDiskUsage(allowDiskUsage); |
423 | } | |
424 | ||
425 | /** | |
426 | * Sets the value of the number of documents to be returned in each | |
427 | * batch. | |
428 | * <p> | |
429 | * This method delegates to {@link #setBatchSize(int)}. | |
430 | * </p> | |
431 | * <p> | |
432 | * This method also sets the builder to use a cursor to true. | |
433 | * </p> | |
434 | * | |
435 | * @param batchSize | |
436 | * The new value for the number of documents to be returned | |
437 | * in each batch. | |
438 | * @return This builder for chaining method calls. | |
439 | */ | |
440 | public Builder batchSize(final int batchSize) { | |
441 | 3 | return setBatchSize(batchSize); |
442 | } | |
443 | ||
444 | /** | |
445 | * Constructs a new {@link Aggregate} object from the state of the | |
446 | * builder. | |
447 | * | |
448 | * @return The new {@link Aggregate} object. | |
449 | */ | |
450 | public Aggregate build() { | |
451 | 81 | return new Aggregate(this); |
452 | } | |
453 | ||
454 | /** | |
455 | * Sets the value of the total number of documents to be returned. | |
456 | * <p> | |
457 | * This method delegates to {@link #setCusorLimit(int)}. | |
458 | * </p> | |
459 | * <p> | |
460 | * This method also sets the builder to use a cursor to true. | |
461 | * </p> | |
462 | * | |
463 | * @param limit | |
464 | * The new value for the total number of documents to be | |
465 | * returned. | |
466 | * @return This builder for chaining method calls. | |
467 | */ | |
468 | public Builder cursorLimit(final int limit) { | |
469 | 2 | return setCusorLimit(limit); |
470 | } | |
471 | ||
472 | /** | |
473 | * Adds a <tt>$geoNear</tt> operation to the pipeline to select | |
474 | * documents for the aggregation pipeline based on their relative | |
475 | * location to a set point. The <tt>$geoNear</tt> must be the first | |
476 | * option in the aggregation pipeline. <blockquote> | |
477 | * | |
478 | * <pre> | |
479 | * <code> | |
480 | * import {@link AggregationGeoNear com.allanbank.mongodb.builder.AggregationGeoNear}; | |
481 | * | |
482 | * {@link Aggregate.Builder} builder = new Aggregation.Builder(); | |
483 | * builder.geoNear( AggregationGeoNear.builder() | |
484 | * .location( new Point( 1, 2 ) ) | |
485 | * .distanceLocationField( "stats.distance" ) | |
486 | * .limit( 5 ).build() ); | |
487 | * </code> | |
488 | * </pre> | |
489 | * | |
490 | * </blockquote> | |
491 | * | |
492 | * @param geoNear | |
493 | * The options for the GeoNear operation. | |
494 | * @return This builder for chaining method calls. | |
495 | * | |
496 | * @since MongoDB 2.4 | |
497 | */ | |
498 | public Builder geoNear(final AggregationGeoNear geoNear) { | |
499 | 1 | myRequiredVersion = Version.later(myRequiredVersion, |
500 | GEO_NEAR_REQUIRED_VERSION); | |
501 | ||
502 | 1 | return step("$geoNear", geoNear.asDocument()); |
503 | } | |
504 | ||
505 | /** | |
506 | * Adds a <tt>$geoNear</tt> operation to the pipeline to select | |
507 | * documents for the aggregation pipeline based on their relative | |
508 | * location to a set point. The <tt>$geoNear</tt> must be the first | |
509 | * option in the aggregation pipeline. <blockquote> | |
510 | * | |
511 | * <pre> | |
512 | * <code> | |
513 | * import {@link AggregationGeoNear com.allanbank.mongodb.builder.AggregationGeoNear}; | |
514 | * | |
515 | * {@link Aggregate.Builder} builder = new Aggregation.Builder(); | |
516 | * builder.geoNear( AggregationGeoNear.builder() | |
517 | * .location( new Point( 1, 2 ) ) | |
518 | * .distanceLocationField( "stats.distance" ) | |
519 | * .limit( 5 ) ); | |
520 | * </code> | |
521 | * </pre> | |
522 | * | |
523 | * </blockquote> | |
524 | * | |
525 | * @param geoNear | |
526 | * The options for the GeoNear operation. | |
527 | * @return This builder for chaining method calls. | |
528 | * | |
529 | * @since MongoDB 2.4 | |
530 | */ | |
531 | public Builder geoNear(final AggregationGeoNear.Builder geoNear) { | |
532 | 1 | return geoNear(geoNear.build()); |
533 | } | |
534 | ||
535 | /** | |
536 | * Adds a <tt>$group</tt> operation to the pipeline to aggregate | |
537 | * documents passing this point in the pipeline into a group of | |
538 | * documents. | |
539 | * <p> | |
540 | * This method is intended to construct groups with simple dynamic or | |
541 | * static id documents. | |
542 | * </p> | |
543 | * <blockquote> | |
544 | * | |
545 | * <pre> | |
546 | * <code> | |
547 | * import static {@link AggregationGroupId#id com.allanbank.mongodb.builder.AggregationGroupId.id}; | |
548 | * import static {@link AggregationGroupField#set com.allanbank.mongodb.builder.AggregationGroupField.set}; | |
549 | * | |
550 | * {@link Aggregate.Builder} builder = new Aggregation.Builder(); | |
551 | * builder.group( | |
552 | * id("$field1"), | |
553 | * set("resultField1").uniqueValuesOf("$field2"), | |
554 | * set("resultField2").max("$field3"), | |
555 | * set("sum").sum("$field4") ); | |
556 | * </code> | |
557 | * </pre> | |
558 | * | |
559 | * </blockquote> | |
560 | * | |
561 | * @param id | |
562 | * The builder for the <tt>_id</tt> field to specify unique | |
563 | * groups. | |
564 | * @param aggregations | |
565 | * The specification for the group id and what fields to | |
566 | * aggregate in the form of a document. | |
567 | * @return This builder for chaining method calls. | |
568 | */ | |
569 | public Builder group(final AggregationGroupId id, | |
570 | final AggregationGroupField... aggregations) { | |
571 | ||
572 | 5 | final Element[] elements = new Element[aggregations.length + 1]; |
573 | 5 | elements[0] = id.toElement(); |
574 | 10 | for (int i = 0; i < aggregations.length; ++i) { |
575 | 5 | elements[i + 1] = aggregations[i].toElement(); |
576 | } | |
577 | ||
578 | 5 | return step("$group", elements); |
579 | } | |
580 | ||
581 | /** | |
582 | * Adds a <tt>$group</tt> operation to the pipeline to aggregate | |
583 | * documents passing this point in the pipeline into a group of | |
584 | * documents. | |
585 | * <p> | |
586 | * This method is intended to construct groups with complex dynamic or | |
587 | * static id documents. The {@link AggregationGroupId.Builder} | |
588 | * implements the {@link DocumentBuilder} for construction of arbitrary | |
589 | * complex _id documents. | |
590 | * </p> | |
591 | * <blockquote> | |
592 | * | |
593 | * <pre> | |
594 | * <code> | |
595 | * import static {@link AggregationGroupId#id com.allanbank.mongodb.builder.AggregationGroupId.id}; | |
596 | * import static {@link AggregationGroupField#set com.allanbank.mongodb.builder.AggregationGroupField.set}; | |
597 | * | |
598 | * {@link Aggregate.Builder} builder = new Aggregation.Builder(); | |
599 | * builder.group( | |
600 | * id().addField("$field1").addField("$field2"), | |
601 | * set("resultField1").uniqueValuesOf("$field3"), | |
602 | * set("resultField2").first("$field4"), | |
603 | * set("count").count() ); | |
604 | * </code> | |
605 | * </pre> | |
606 | * | |
607 | * </blockquote> | |
608 | * | |
609 | * @param id | |
610 | * The builder for the <tt>_id</tt> field to specify unique | |
611 | * groups. | |
612 | * @param aggregations | |
613 | * The specification for the group id and what fields to | |
614 | * aggregate in the form of a document. | |
615 | * @return This builder for chaining method calls. | |
616 | */ | |
617 | public Builder group(final AggregationGroupId.Builder id, | |
618 | final AggregationGroupField... aggregations) { | |
619 | 2 | return group(id.buildId(), aggregations); |
620 | } | |
621 | ||
622 | /** | |
623 | * Adds a <tt>$group</tt> operation to the pipeline to aggregate | |
624 | * documents passing this point in the pipeline into a group of | |
625 | * documents. | |
626 | * | |
627 | * @param aggregations | |
628 | * The specification for the group id and what fields to | |
629 | * aggregate in the form of a document. | |
630 | * @return This builder for chaining method calls. | |
631 | */ | |
632 | public Builder group(final DocumentAssignable aggregations) { | |
633 | 1 | return step("$group", aggregations); |
634 | } | |
635 | ||
636 | /** | |
637 | * Adds a <tt>$group</tt> operation to the pipeline to aggregate | |
638 | * documents passing this point in the pipeline into a group of | |
639 | * documents. | |
640 | * <p> | |
641 | * This method is intended to construct groups with complex dynamic or | |
642 | * static id documents. The {@link AggregationGroupId.Builder} | |
643 | * implements the {@link DocumentBuilder} for construction of arbitrary | |
644 | * complex _id documents. | |
645 | * </p> | |
646 | * <blockquote> | |
647 | * | |
648 | * <pre> | |
649 | * <code> | |
650 | * import static {@link AggregationGroupId#id com.allanbank.mongodb.builder.AggregationGroupId.id}; | |
651 | * import static {@link AggregationGroupField#set com.allanbank.mongodb.builder.AggregationGroupField.set}; | |
652 | * | |
653 | * {@link Aggregate.Builder} builder = new Aggregation.Builder(); | |
654 | * builder.group( | |
655 | * id().addInteger("i", 1), | |
656 | * set("resultField1").uniqueValuesOf("$field3"), | |
657 | * set("resultField2").first("$field4"), | |
658 | * set("count").count() ); | |
659 | * </code> | |
660 | * </pre> | |
661 | * | |
662 | * </blockquote> | |
663 | * | |
664 | * @param id | |
665 | * The builder for the <tt>_id</tt> field to specify unique | |
666 | * groups. | |
667 | * @param aggregations | |
668 | * The specification for the group id and what fields to | |
669 | * aggregate in the form of a document. | |
670 | * @return This builder for chaining method calls. | |
671 | */ | |
672 | public Builder group(final DocumentAssignable id, | |
673 | final AggregationGroupField... aggregations) { | |
674 | 1 | return group(new AggregationGroupId(id), aggregations); |
675 | } | |
676 | ||
677 | /** | |
678 | * Adds a <tt>$limit</tt> operation to the pipeline to stop producing | |
679 | * documents passing this point in the pipeline once the limit of | |
680 | * documents is reached. | |
681 | * | |
682 | * @param numberOfDocuments | |
683 | * The number of documents to allow past this point in the | |
684 | * pipeline. | |
685 | * @return This builder for chaining method calls. | |
686 | * | |
687 | * @see <a | |
688 | * href="http://docs.mongodb.org/manual/reference/aggregation/#_S_limit">Aggregation | |
689 | * Framework Operators - $limit</a> | |
690 | */ | |
691 | public Builder limit(final int numberOfDocuments) { | |
692 | 20 | return step("$limit", numberOfDocuments); |
693 | } | |
694 | ||
695 | /** | |
696 | * Adds a <tt>$limit</tt> operation to the pipeline to stop producing | |
697 | * documents passing this point in the pipeline once the limit of | |
698 | * documents is reached. | |
699 | * | |
700 | * @param numberOfDocuments | |
701 | * The number of documents to allow past this point in the | |
702 | * pipeline. | |
703 | * @return This builder for chaining method calls. | |
704 | * | |
705 | * @see <a | |
706 | * href="http://docs.mongodb.org/manual/reference/aggregation/#_S_limit"> | |
707 | * Aggregation Framework Operators - $limit</a> | |
708 | */ | |
709 | public Builder limit(final long numberOfDocuments) { | |
710 | 1 | return step("$limit", numberOfDocuments); |
711 | } | |
712 | ||
713 | /** | |
714 | * Adds a <tt>$match</tt> operation to the pipeline to filter documents | |
715 | * passing this point in the pipeline. | |
716 | * <p> | |
717 | * This method may be used with the {@link QueryBuilder} to easily | |
718 | * specify the criteria to match against. <blockquote> | |
719 | * | |
720 | * <pre> | |
721 | * <code> | |
722 | * import static {@link QueryBuilder#where com.allanbank.mongodb.builder.QueryBuilder.where} | |
723 | * | |
724 | * Aggregation.Builder builder = new Aggregation.Builder(); | |
725 | * | |
726 | * builder.match( where("f").greaterThan(23).lessThan(42).and("g").lessThan(3) ); | |
727 | * ... | |
728 | * </code> | |
729 | * </pre> | |
730 | * | |
731 | * </blockquote> | |
732 | * </p> | |
733 | * | |
734 | * @param query | |
735 | * The query to match documents against. | |
736 | * @return This builder for chaining method calls. | |
737 | * | |
738 | * @see <a | |
739 | * href="http://docs.mongodb.org/manual/reference/aggregation/#_S_match"> | |
740 | * Aggregation Framework Operators - $match</a> | |
741 | */ | |
742 | public Builder match(final DocumentAssignable query) { | |
743 | 5 | return step("$match", query); |
744 | } | |
745 | ||
746 | /** | |
747 | * Sets the maximum number of milliseconds to allow the command to run | |
748 | * before aborting the request on the server. | |
749 | * <p> | |
750 | * This method equivalent to {@link #setMaximumTimeMilliseconds(long) | |
751 | * setMaximumTimeMilliseconds(timeLimitUnits.toMillis(timeLimit)}. | |
752 | * </p> | |
753 | * | |
754 | * @param timeLimit | |
755 | * The new maximum amount of time to allow the command to | |
756 | * run. | |
757 | * @param timeLimitUnits | |
758 | * The units for the maximum amount of time to allow the | |
759 | * command to run. | |
760 | * | |
761 | * @return This {@link Builder} for method call chaining. | |
762 | * | |
763 | * @since MongoDB 2.6 | |
764 | */ | |
765 | public Builder maximumTime(final long timeLimit, | |
766 | final TimeUnit timeLimitUnits) { | |
767 | 2 | return setMaximumTimeMilliseconds(timeLimitUnits |
768 | .toMillis(timeLimit)); | |
769 | } | |
770 | ||
771 | /** | |
772 | * Adds a <tt>$out</tt> operation to the pipeline to write all of the | |
773 | * output documents to the specified collection. | |
774 | * <p> | |
775 | * This method also forces the {@link ReadPreference} to be | |
776 | * {@link ReadPreference#PRIMARY}. | |
777 | * </p> | |
778 | * | |
779 | * @param collectionName | |
780 | * The name of the collection to output the results to. | |
781 | * @return This builder for chaining method calls. | |
782 | * | |
783 | * @see <a | |
784 | * href="http://docs.mongodb.org/master/reference/operator/aggregation/out">Aggregation | |
785 | * $out Operator</a> | |
786 | */ | |
787 | public Builder out(final String collectionName) { | |
788 | 1 | setReadPreference(ReadPreference.PRIMARY); |
789 | 1 | return step("$out", collectionName); |
790 | } | |
791 | ||
792 | /** | |
793 | * Adds a <tt>$project</tt> operation to the pipeline to create a | |
794 | * projection of the documents passing this point in the pipeline. | |
795 | * <p> | |
796 | * This method is intended to be used with the | |
797 | * {@link AggregationProjectFields} and | |
798 | * {@link com.allanbank.mongodb.builder.expression.Expressions | |
799 | * Expressions} static helper methods. | |
800 | * </p> | |
801 | * <blockquote> | |
802 | * | |
803 | * <pre> | |
804 | * <code> | |
805 | * import static {@link AggregationProjectFields#include com.allanbank.mongodb.builder.AggregationProjectFields.include}; | |
806 | * import static {@link com.allanbank.mongodb.builder.expression.Expressions com.allanbank.mongodb.builder.expression.Expressions.*}; | |
807 | * | |
808 | * | |
809 | * Aggregation.Builder builder = new Aggregation.Builder(); | |
810 | * ... | |
811 | * builder.project( | |
812 | * include("chr", "begin", "end", "calledPloidy"), | |
813 | * set("window", | |
814 | * multiply( | |
815 | * divide( | |
816 | * subtract( | |
817 | * field("begin"), | |
818 | * mod(field("begin"), constant(interval))), | |
819 | * constant(interval)), | |
820 | * constant(interval)))); | |
821 | * ... | |
822 | * </code> | |
823 | * </pre> | |
824 | * | |
825 | * </blockquote> | |
826 | * | |
827 | * @param fields | |
828 | * The fields to copy into the projected results. | |
829 | * @param elements | |
830 | * The computed elements based on {@link Expressions}. | |
831 | * @return This builder for chaining method calls. | |
832 | */ | |
833 | public Builder project(final AggregationProjectFields fields, | |
834 | final Element... elements) { | |
835 | 3 | final List<IntegerElement> fieldElements = fields.toElements(); |
836 | ||
837 | 3 | final List<Element> allElements = new ArrayList<Element>( |
838 | fieldElements.size() + elements.length); | |
839 | 3 | allElements.addAll(fieldElements); |
840 | 3 | allElements.addAll(Arrays.asList(elements)); |
841 | ||
842 | 3 | return step("$project", allElements); |
843 | } | |
844 | ||
845 | /** | |
846 | * Adds a <tt>$project</tt> operation to the pipeline to create a | |
847 | * projection of the documents passing this point in the pipeline. | |
848 | * | |
849 | * @param projection | |
850 | * The specification for the projection to perform. | |
851 | * @return This builder for chaining method calls. | |
852 | */ | |
853 | public Builder project(final DocumentAssignable projection) { | |
854 | 1 | return step("$project", projection); |
855 | } | |
856 | ||
857 | /** | |
858 | * Adds a <tt>$redact</tt> operation to potentially prune sub-documents | |
859 | * from the results. | |
860 | * | |
861 | * @param ifExpression | |
862 | * The expression to evaluate to determine if the current | |
863 | * sub-document should be pruned or not. | |
864 | * @param thenOption | |
865 | * Operation to apply if the {@code ifExpression} evaluates | |
866 | * to true. | |
867 | * @param elseOption | |
868 | * Operation to apply if the {@code ifExpression} evaluates | |
869 | * to false. | |
870 | * @return This builder for chaining method calls. | |
871 | */ | |
872 | public Builder redact(final DocumentAssignable ifExpression, | |
873 | final RedactOption thenOption, final RedactOption elseOption) { | |
874 | 1 | myRequiredVersion = Version.later(myRequiredVersion, |
875 | REDACT_REQUIRED_VERSION); | |
876 | ||
877 | 1 | final DocumentBuilder doc = BuilderFactory.start(); |
878 | 1 | doc.push(Expressions.CONDITION) |
879 | .add(new DocumentElement("if", ifExpression.asDocument())) | |
880 | .add("then", thenOption.getToken()) | |
881 | .add("else", elseOption.getToken()); | |
882 | ||
883 | 1 | return step("$redact", doc); |
884 | } | |
885 | ||
886 | /** | |
887 | * Adds a <tt>$redact</tt> operation to potentially prune sub-documents | |
888 | * from the results. | |
889 | * | |
890 | * @param ifExpression | |
891 | * The expression to evaluate to determine if the current | |
892 | * sub-document should be pruned or not. | |
893 | * @param thenOption | |
894 | * Operation to apply if the {@code ifExpression} evaluates | |
895 | * to true. | |
896 | * @param elseOption | |
897 | * Operation to apply if the {@code ifExpression} evaluates | |
898 | * to false. | |
899 | * @return This builder for chaining method calls. | |
900 | */ | |
901 | public Builder redact(final Expression ifExpression, | |
902 | final RedactOption thenOption, final RedactOption elseOption) { | |
903 | 1 | myRequiredVersion = Version.later(myRequiredVersion, |
904 | REDACT_REQUIRED_VERSION); | |
905 | ||
906 | 1 | final DocumentBuilder doc = BuilderFactory.start(); |
907 | 1 | doc.push(Expressions.CONDITION).add(ifExpression.toElement("if")) |
908 | .add("then", thenOption.getToken()) | |
909 | .add("else", elseOption.getToken()); | |
910 | ||
911 | 1 | return step("$redact", doc); |
912 | } | |
913 | ||
914 | /** | |
915 | * Resets the builder back to an empty pipeline. | |
916 | * | |
917 | * @return This builder for chaining method calls. | |
918 | */ | |
919 | public Builder reset() { | |
920 | 94 | myPipeline.reset(); |
921 | 94 | myReadPreference = null; |
922 | 94 | myMaximumTimeMilliseconds = 0; |
923 | 94 | myBatchSize = 0; |
924 | 94 | myLimit = 0; |
925 | 94 | myUseCursor = false; |
926 | 94 | myAllowDiskUsage = false; |
927 | 94 | myRequiredVersion = REQUIRED_VERSION; |
928 | ||
929 | 94 | return this; |
930 | } | |
931 | ||
932 | /** | |
933 | * Sets to true if the aggregation command can spill to disk. | |
934 | * <p> | |
935 | * This method also sets the builder to use a cursor to true. | |
936 | * </p> | |
937 | * | |
938 | * @param allowDiskUsage | |
939 | * The new value for if the aggregation command can spill to | |
940 | * disk. | |
941 | * @return This builder for chaining method calls. | |
942 | */ | |
943 | public Builder setAllowDiskUsage(final boolean allowDiskUsage) { | |
944 | 2 | myRequiredVersion = Version.later(myRequiredVersion, |
945 | ALLOW_DISK_USAGE_REQUIRED_VERSION); | |
946 | ||
947 | 2 | myAllowDiskUsage = allowDiskUsage; |
948 | 2 | return setUseCursor(true); |
949 | } | |
950 | ||
951 | /** | |
952 | * Sets the value of the number of documents to be returned in each | |
953 | * batch. | |
954 | * <p> | |
955 | * This method also sets the builder to use a cursor to true. | |
956 | * </p> | |
957 | * | |
958 | * @param batchSize | |
959 | * The new value for the number of documents to be returned | |
960 | * in each batch. | |
961 | * @return This builder for chaining method calls. | |
962 | */ | |
963 | public Builder setBatchSize(final int batchSize) { | |
964 | 3 | myBatchSize = batchSize; |
965 | 3 | return setUseCursor(true); |
966 | } | |
967 | ||
968 | /** | |
969 | * Sets the value of the total number of documents to be returned. | |
970 | * <p> | |
971 | * This method also sets the builder to use a cursor to true. | |
972 | * </p> | |
973 | * | |
974 | * @param limit | |
975 | * The new value for the total number of documents to be | |
976 | * returned. | |
977 | * @return This builder for chaining method calls. | |
978 | */ | |
979 | public Builder setCusorLimit(final int limit) { | |
980 | 2 | myLimit = limit; |
981 | 2 | return setUseCursor(true); |
982 | } | |
983 | ||
984 | /** | |
985 | * Sets the maximum number of milliseconds to allow the command to run | |
986 | * before aborting the request on the server. | |
987 | * | |
988 | * @param maximumTimeMilliseconds | |
989 | * The new maximum number of milliseconds to allow the | |
990 | * command to run. | |
991 | * @return This {@link Builder} for method call chaining. | |
992 | * | |
993 | * @since MongoDB 2.6 | |
994 | */ | |
995 | public Builder setMaximumTimeMilliseconds( | |
996 | final long maximumTimeMilliseconds) { | |
997 | 3 | myRequiredVersion = Version.later(myRequiredVersion, |
998 | MAX_TIMEOUT_VERSION); | |
999 | ||
1000 | 3 | myMaximumTimeMilliseconds = maximumTimeMilliseconds; |
1001 | 3 | return this; |
1002 | } | |
1003 | ||
1004 | /** | |
1005 | * Sets the {@link ReadPreference} specifying which servers may be used | |
1006 | * to execute the aggregation. | |
1007 | * <p> | |
1008 | * If not set or set to <code>null</code> then the | |
1009 | * {@link MongoCollection} instance's {@link ReadPreference} will be | |
1010 | * used. | |
1011 | * </p> | |
1012 | * | |
1013 | * @param readPreference | |
1014 | * The read preferences specifying which servers may be used. | |
1015 | * @return This builder for chaining method calls. | |
1016 | * | |
1017 | * @see MongoCollection#getReadPreference() | |
1018 | */ | |
1019 | public Builder setReadPreference(final ReadPreference readPreference) { | |
1020 | 4 | myReadPreference = readPreference; |
1021 | 4 | return this; |
1022 | } | |
1023 | ||
1024 | /** | |
1025 | * Sets to true if the aggregation results should be returned as a | |
1026 | * cursor. | |
1027 | * | |
1028 | * @param useCursor | |
1029 | * The new value for if the results should be returned via a | |
1030 | * cursor. | |
1031 | * @return This builder for chaining method calls. | |
1032 | */ | |
1033 | public Builder setUseCursor(final boolean useCursor) { | |
1034 | 9 | myRequiredVersion = Version |
1035 | .later(myRequiredVersion, CURSOR_VERSION); | |
1036 | 9 | myUseCursor = useCursor; |
1037 | 9 | return this; |
1038 | } | |
1039 | ||
1040 | /** | |
1041 | * Adds a <tt>$skip</tt> operation to the pipeline to skip the specified | |
1042 | * number of documents before allowing any document past this point in | |
1043 | * the pipeline. | |
1044 | * | |
1045 | * @param numberOfDocuments | |
1046 | * The number of documents to skip past before allowing any | |
1047 | * documents to pass this point in the pipeline. | |
1048 | * @return This builder for chaining method calls. | |
1049 | * | |
1050 | * @see <a | |
1051 | * href="http://docs.mongodb.org/manual/reference/aggregation/#_S_skip"> | |
1052 | * Aggregation Framework Operators - $skip</a> | |
1053 | */ | |
1054 | public Builder skip(final int numberOfDocuments) { | |
1055 | 2 | return step("$skip", numberOfDocuments); |
1056 | } | |
1057 | ||
1058 | /** | |
1059 | * Adds a <tt>$skip</tt> operation to the pipeline to skip the specified | |
1060 | * number of documents before allowing any document past this point in | |
1061 | * the pipeline. | |
1062 | * | |
1063 | * @param numberOfDocuments | |
1064 | * The number of documents to skip past before allowing any | |
1065 | * documents to pass this point in the pipeline. | |
1066 | * @return This builder for chaining method calls. | |
1067 | * | |
1068 | * @see <a | |
1069 | * href="http://docs.mongodb.org/manual/reference/aggregation/#_S_skip"> | |
1070 | * Aggregation Framework Operators - $skip</a> | |
1071 | */ | |
1072 | public Builder skip(final long numberOfDocuments) { | |
1073 | 1 | return step("$skip", numberOfDocuments); |
1074 | } | |
1075 | ||
1076 | /** | |
1077 | * Adds a <tt>$sort</tt> operation to sort the documents passing this | |
1078 | * point based on the sort specification provided. | |
1079 | * <p> | |
1080 | * This method is intended to be used with the {@link Sort} class's | |
1081 | * static methods: <blockquote> | |
1082 | * | |
1083 | * <pre> | |
1084 | * <code> | |
1085 | * import static {@link Sort#asc(String) com.allanbank.mongodb.builder.Sort.asc}; | |
1086 | * import static {@link Sort#desc(String) com.allanbank.mongodb.builder.Sort.desc}; | |
1087 | * | |
1088 | * Aggregation.Builder builder = new Aggregation.Builder(); | |
1089 | * | |
1090 | * builder.setSort( asc("f"), desc("g") ); | |
1091 | * ... | |
1092 | * </code> | |
1093 | * </pre> | |
1094 | * | |
1095 | * </blockquote> | |
1096 | * | |
1097 | * @param sortFields | |
1098 | * The sort fields to use. | |
1099 | * @return This builder for chaining method calls. | |
1100 | * | |
1101 | * @see <a | |
1102 | * href="http://docs.mongodb.org/manual/reference/aggregation/#_S_sort"> | |
1103 | * Aggregation Framework Operators - $sort</a> | |
1104 | */ | |
1105 | public Builder sort(final IntegerElement... sortFields) { | |
1106 | 2 | return step("$sort", sortFields); |
1107 | } | |
1108 | ||
1109 | /** | |
1110 | * Adds a <tt>$sort</tt> operation to sort the documents passing this | |
1111 | * point based on the sort fields provides in ascending order. | |
1112 | * | |
1113 | * @param sortFields | |
1114 | * The sort fields to use in ascending order. | |
1115 | * @return This builder for chaining method calls. | |
1116 | * | |
1117 | * @see <a | |
1118 | * href="http://docs.mongodb.org/manual/reference/aggregation/#_S_sort"> | |
1119 | * Aggregation Framework Operators - $sort</a> | |
1120 | */ | |
1121 | public Builder sort(final String... sortFields) { | |
1122 | 1 | final IntegerElement[] elements = new IntegerElement[sortFields.length]; |
1123 | 3 | for (int i = 0; i < sortFields.length; ++i) { |
1124 | 2 | elements[i] = Sort.asc(sortFields[i]); |
1125 | } | |
1126 | 1 | return sort(elements); |
1127 | } | |
1128 | ||
1129 | /** | |
1130 | * Adds a generic step to the builder's pipeline. | |
1131 | * | |
1132 | * @param operator | |
1133 | * The operator to add to the pipeline. | |
1134 | * @param stepDocument | |
1135 | * The document containing the details of the step to apply. | |
1136 | * @return This builder for chaining method calls. | |
1137 | */ | |
1138 | public Builder step(final String operator, | |
1139 | final DocumentAssignable stepDocument) { | |
1140 | 11 | myPipeline.push().addDocument(operator, stepDocument.asDocument()); |
1141 | 11 | return this; |
1142 | } | |
1143 | ||
1144 | /** | |
1145 | * Adds a generic step to the builder's pipeline. | |
1146 | * | |
1147 | * @param operator | |
1148 | * The operator to add to the pipeline. | |
1149 | * @param value | |
1150 | * The value for the operator. | |
1151 | * @return This builder for chaining method calls. | |
1152 | */ | |
1153 | public Builder step(final String operator, final double value) { | |
1154 | 1 | myPipeline.push().addDouble(operator, value); |
1155 | 1 | return this; |
1156 | } | |
1157 | ||
1158 | /** | |
1159 | * Adds a generic step to the builder's pipeline. | |
1160 | * | |
1161 | * @param operator | |
1162 | * The operator to add to the pipeline. | |
1163 | * @param elements | |
1164 | * The elements containing the details of the step to apply. | |
1165 | * @return This builder for chaining method calls. | |
1166 | */ | |
1167 | public Builder step(final String operator, final Element... elements) { | |
1168 | 8 | return step(operator, Arrays.asList(elements)); |
1169 | } | |
1170 | ||
1171 | /** | |
1172 | * Adds a generic step to the builder's pipeline. | |
1173 | * | |
1174 | * @param operator | |
1175 | * The operator to add to the pipeline. | |
1176 | * @param value | |
1177 | * The value for the operator. | |
1178 | * @return This builder for chaining method calls. | |
1179 | */ | |
1180 | public Builder step(final String operator, final int value) { | |
1181 | 23 | myPipeline.push().addInteger(operator, value); |
1182 | 23 | return this; |
1183 | } | |
1184 | ||
1185 | /** | |
1186 | * Adds a generic step to the builder's pipeline. | |
1187 | * | |
1188 | * @param operator | |
1189 | * The operator to add to the pipeline. | |
1190 | * @param elements | |
1191 | * The elements containing the details of the step to apply. | |
1192 | * @return This builder for chaining method calls. | |
1193 | */ | |
1194 | public Builder step(final String operator, final List<Element> elements) { | |
1195 | 12 | final DocumentBuilder operatorBuilder = myPipeline.push().push( |
1196 | operator); | |
1197 | 12 | for (final Element element : elements) { |
1198 | 34 | operatorBuilder.add(element); |
1199 | 34 | } |
1200 | 12 | return this; |
1201 | } | |
1202 | ||
1203 | /** | |
1204 | * Adds a generic step to the builder's pipeline. | |
1205 | * | |
1206 | * @param operator | |
1207 | * The operator to add to the pipeline. | |
1208 | * @param value | |
1209 | * The value for the operator. | |
1210 | * @return This builder for chaining method calls. | |
1211 | */ | |
1212 | public Builder step(final String operator, final long value) { | |
1213 | 3 | myPipeline.push().addLong(operator, value); |
1214 | 3 | return this; |
1215 | } | |
1216 | ||
1217 | /** | |
1218 | * Adds a generic step to the builder's pipeline. | |
1219 | * | |
1220 | * @param operator | |
1221 | * The operator to add to the pipeline. | |
1222 | * @param value | |
1223 | * The value for the operator. | |
1224 | * @return This builder for chaining method calls. | |
1225 | */ | |
1226 | public Builder step(final String operator, final String value) { | |
1227 | 4 | myPipeline.push().addString(operator, value); |
1228 | 4 | return this; |
1229 | } | |
1230 | ||
1231 | /** | |
1232 | * Return the JSON for the current pipeline that would be constructed by | |
1233 | * the builder. | |
1234 | */ | |
1235 | @Override | |
1236 | public String toString() { | |
1237 | 0 | return new ArrayElement("$pipeline", build().getPipeline()) |
1238 | .toString(); | |
1239 | } | |
1240 | ||
1241 | /** | |
1242 | * Adds a <tt>$unwind</tt> operation generate a document for each | |
1243 | * element of the specified array field with the array replaced with the | |
1244 | * value of the element. | |
1245 | * | |
1246 | * @param fieldName | |
1247 | * The name of the array field within the document to unwind. | |
1248 | * This name must start with a '$'. If it does not a '$' will | |
1249 | * be prepended to the field name.. | |
1250 | * @return This builder for chaining method calls. | |
1251 | * | |
1252 | * @see <a | |
1253 | * href="http://docs.mongodb.org/manual/reference/aggregation/#_S_unwind"> | |
1254 | * Aggregation Framework Operators - $unwind</a> | |
1255 | */ | |
1256 | public Builder unwind(final String fieldName) { | |
1257 | 2 | if (fieldName.startsWith("$")) { |
1258 | 1 | step("$unwind", fieldName); |
1259 | } | |
1260 | else { | |
1261 | 1 | step("$unwind", "$" + fieldName); |
1262 | } | |
1263 | 2 | return this; |
1264 | } | |
1265 | ||
1266 | /** | |
1267 | * Sets that the results should be returned using a cursor. | |
1268 | * <p> | |
1269 | * This method delegates to {@link #setUseCursor(boolean) | |
1270 | * setUseCursor(true)}. | |
1271 | * </p> | |
1272 | * | |
1273 | * @return This builder for chaining method calls. | |
1274 | */ | |
1275 | public Builder useCursor() { | |
1276 | 1 | return setUseCursor(true); |
1277 | } | |
1278 | ||
1279 | /** | |
1280 | * Sets to true if the aggregation results should be returned as a | |
1281 | * cursor. | |
1282 | * <p> | |
1283 | * This method delegates to {@link #setUseCursor(boolean)}. | |
1284 | * </p> | |
1285 | * | |
1286 | * @param useCursor | |
1287 | * The new value for if the results should be returned via a | |
1288 | * cursor. | |
1289 | * @return This builder for chaining method calls. | |
1290 | */ | |
1291 | public Builder useCursor(final boolean useCursor) { | |
1292 | 1 | return setUseCursor(useCursor); |
1293 | } | |
1294 | } | |
1295 | } |