Compare commits

..

168 Commits

Author SHA1 Message Date
Mark Paluch
c89f707966 DATAMONGO-2624 - Release version 2.2.11 (Moore SR11). 2020-10-28 11:44:36 +01:00
Mark Paluch
b1764160c5 DATAMONGO-2624 - Prepare 2.2.11 (Moore SR11). 2020-10-28 11:44:06 +01:00
Mark Paluch
7e1e33d51f DATAMONGO-2624 - Updated changelog. 2020-10-28 11:43:53 +01:00
Mark Paluch
2a81418738 DATAMONGO-2641 - Updated changelog. 2020-10-28 11:32:30 +01:00
Robin Dupret
f72a961bb4 DATAMONGO-2638 - Fix list item rendering in reference documentation.
Original Pull Request: #885
2020-10-27 13:33:40 +01:00
LiangYong
e398bf8a24 DATAMONGO-2638 - Fix aggregation input parameter syntax in reference documentation.
Original Pull Request: #881
2020-10-27 13:33:36 +01:00
Christoph Strobl
7787a5cf0e DATAMONGO-2626 - Updated changelog. 2020-10-14 14:51:52 +02:00
Mark Paluch
0786969ef2 DATAMONGO-2616 - Polishing.
Reformat code. Merge if-statements.

Original pull request: #889.
2020-10-07 11:36:01 +02:00
Christoph Strobl
98040ad44e DATAMONGO-2616 - Short circuit id value assignment in MongoConverter.
Original pull request: #889.
2020-10-07 11:36:01 +02:00
Christoph Strobl
ad4ab65a9f DATAMONGO-2633 - Fix json parsing of nested arrays in ParameterBindingDocumentCodec.
Original pull request: #888.
2020-10-05 15:42:07 +02:00
Mark Paluch
e05113ea27 DATAMONGO-2608 - Updated changelog. 2020-09-16 14:12:07 +02:00
Mark Paluch
c78898edf7 DATAMONGO-2609 - Updated changelog. 2020-09-16 12:16:36 +02:00
Mark Paluch
9f6be1f471 DATAMONGO-2593 - After release cleanups. 2020-09-16 11:19:26 +02:00
Mark Paluch
f8a48637ec DATAMONGO-2593 - Prepare next development iteration. 2020-09-16 11:19:23 +02:00
Mark Paluch
df73c567ce DATAMONGO-2593 - Release version 2.2.10 (Moore SR10). 2020-09-16 10:53:21 +02:00
Mark Paluch
47ce8258b0 DATAMONGO-2593 - Prepare 2.2.10 (Moore SR10). 2020-09-16 10:52:53 +02:00
Mark Paluch
e523d9a1cb DATAMONGO-2593 - Updated changelog. 2020-09-16 10:52:37 +02:00
Mark Paluch
d65632c097 DATAMONGO-2592 - Updated changelog. 2020-09-16 10:39:00 +02:00
Christoph Strobl
29bf4f72f3 DATAMONGO-2618 - Fix visibility of ReplaceRootDocumentOperation. 2020-09-14 13:46:20 +02:00
Michal Kurcius
ee79b9939b DATAMONGO-2613 - Fix single element ArrayJsonSchemaObject to document mapping.
Now toDocument calls toDocument on items correctly.

Original Pull Request: #883
2020-08-20 09:13:09 +02:00
Mark Paluch
156ec5b441 DATAMONGO-2594 - Updated changelog. 2020-08-12 13:25:53 +02:00
Mark Paluch
931028b43e DATAMONGO-2579 - Updated changelog. 2020-08-12 12:01:24 +02:00
Mark Paluch
687c4d35ed DATAMONGO-2599 - Eagerly consider enum types as simple types.
MongoSimpleTypes now eagerly checks if a type is a simple one to avoid PersistentEntity registration for ChronoUnit.
2020-07-30 16:36:37 +02:00
Mark Paluch
71ac036dc3 DATAMONGO-2568 - Updated changelog. 2020-07-22 10:38:03 +02:00
Mark Paluch
da3ab42f10 DATAMONGO-2567 - After release cleanups. 2020-07-22 10:07:19 +02:00
Mark Paluch
537fc1caad DATAMONGO-2567 - Prepare next development iteration. 2020-07-22 10:07:16 +02:00
Mark Paluch
0ec0eaf937 DATAMONGO-2567 - Release version 2.2.9 (Moore SR9). 2020-07-22 09:55:55 +02:00
Mark Paluch
1babda2e69 DATAMONGO-2567 - Prepare 2.2.9 (Moore SR9). 2020-07-22 09:55:29 +02:00
Mark Paluch
e319ea82d0 DATAMONGO-2567 - Updated changelog. 2020-07-22 09:55:18 +02:00
Mark Paluch
63c8f63acf DATAMONGO-2566 - Updated changelog. 2020-07-22 09:44:31 +02:00
Mark Paluch
4f7d3131c5 DATAMONGO-2571 - Polishing.
Fix test method visibility.
2020-07-15 15:45:11 +02:00
Christoph Strobl
6a8609c7f8 DATAMONGO-2571 - Fix regular expression parameter binding for String-based queries.
Original pull request: #873.
2020-07-15 15:33:57 +02:00
Mark Paluch
d9477501ae DATAMONGO-2490 - Polishing.
Remove unnecessary code. Reuse session-associated collection when logging to avoid unqualified calls to MongoDbFactory.getMongoDatabase(). Create collection before transaction in test for compatibility with older MongoDB servers.

Original pull request: #875.
2020-07-15 15:17:26 +02:00
Christoph Strobl
be46540959 DATAMONGO-2490 - Fix dbref fetching during ongoing transaction.
Original pull request: #875.
2020-07-15 15:16:20 +02:00
Mark Paluch
773f20f861 DATAMONGO-2544 - Updated changelog. 2020-06-25 12:00:21 +02:00
Mark Paluch
171386baaf DATAMONGO-2570 - Polishing.
Add assertions. Use method references where possible.

Original pull request: #871.
2020-06-22 10:40:16 +02:00
Mehran Behnam
aa2716c2c0 DATAMONGO-2570 - Change type of count variable to primitive.
Avoiding unintentional unboxing.

Original pull request: #871.
2020-06-22 10:40:16 +02:00
Mark Paluch
1904a809a4 DATAMONGO-2572 - Remove usage of Oppressive Language.
Replaced blacklist with denylist and introduce meta keyword SECONDARY_READS as we no longer use MongoDB API with the initial replication concept.

Original Pull Request: #870
2020-06-17 13:49:04 +02:00
Mark Paluch
f8dddc366b DATAMONGO-2543 - Updated changelog. 2020-06-10 14:31:01 +02:00
Mark Paluch
f7bc5228ec DATAMONGO-2533 - After release cleanups. 2020-06-10 12:29:17 +02:00
Mark Paluch
4782900da5 DATAMONGO-2533 - Prepare next development iteration. 2020-06-10 12:29:14 +02:00
Mark Paluch
c011ff81b9 DATAMONGO-2533 - Release version 2.2.8 (Moore SR8). 2020-06-10 12:11:27 +02:00
Mark Paluch
cb768ce953 DATAMONGO-2533 - Prepare 2.2.8 (Moore SR8). 2020-06-10 12:11:00 +02:00
Mark Paluch
5d08c040b9 DATAMONGO-2533 - Updated changelog. 2020-06-10 12:10:46 +02:00
Mark Paluch
7a0f38d10e DATAMONGO-2532 - Updated changelog. 2020-06-10 11:22:53 +02:00
Mark Paluch
1e9ab02e3f DATAMONGO-2565 - Polishing.
Add unit test to verify behavior. Cleanup code.

Original pull request: #869.
2020-06-10 10:16:03 +02:00
BraveLeeLee
5e378bd21b DATAMONGO-2565 - Evaluate correct expression when obtaining collation from MongoPersistentEntity.
Original pull request: #869.
2020-06-10 10:15:29 +02:00
Mark Paluch
a2e5009f42 DATAMONGO-2542 - Polishing.
Fix nullable annotation.

Original pull request: #863.
2020-05-26 10:32:43 +02:00
Christoph Strobl
44cc0dad94 DATAMONGO-2542 - Shortcut PersistentPropertyPath resolution during query mapping.
By shortcutting the path resolution we avoid checking keywords like $in against a potential path expression.

Original pull request: #863.
2020-05-26 10:32:43 +02:00
Mark Paluch
68de8e57be DATAMONGO-2545 - Polishing.
Fix warnings and typos.

Original pull request: #864.
2020-05-26 10:24:31 +02:00
Christoph Strobl
fde59411da DATAMONGO-2545 - Fix full Query Document binding resulting from SpEL.
We reenabled annotated queries using a SpEL expression resulting in the actual query document.

Original pull request: #864.
2020-05-26 10:18:46 +02:00
Christoph Strobl
7d48dd0ce4 DATAMONGO-2545 - Fix regression in String query SpEL parameter binding.
We reenabled parameter binding within SpEL using query parameter placeholders ?0, ?1,... instead of their array index [0],[1],...

Original pull request: #864.
2020-05-26 10:18:44 +02:00
Christoph Strobl
699a7a00f5 DATAMONGO-2547 - Use target class ClassLoader instead of default CL when creating proxy instances.
Original pull request: #865.
2020-05-26 08:50:30 +02:00
Mark Paluch
16d55c8973 DATAMONGO-2509 - Add missing Query constructor in reference documentation.
Original pull request: #846.
2020-05-06 11:52:53 +02:00
Christoph Strobl
be0b9415b4 DATAMONGO-2509 - Update Javadoc.
Original pull request: #853.
2020-05-06 11:41:25 +02:00
Greg Turnquist
93df58a8d5 DATAMONGO-2535 - Remove Travis CI. 2020-05-04 15:09:18 -05:00
Mark Paluch
999e24902c DATAMONGO-2503 - Updated changelog. 2020-04-28 15:12:28 +02:00
Mark Paluch
d19208abec DATAMONGO-2500 - After release cleanups. 2020-04-28 14:45:30 +02:00
Mark Paluch
8f54676b97 DATAMONGO-2500 - Prepare next development iteration. 2020-04-28 14:45:29 +02:00
Mark Paluch
61bbc9ab7f DATAMONGO-2500 - Release version 2.2.7 (Moore SR7). 2020-04-28 14:35:55 +02:00
Mark Paluch
9e802a59c7 DATAMONGO-2500 - Prepare 2.2.7 (Moore SR7). 2020-04-28 14:35:24 +02:00
Mark Paluch
38e1e632a7 DATAMONGO-2500 - Updated changelog. 2020-04-28 14:35:16 +02:00
Mark Paluch
89cf78cc4a DATAMONGO-2484 - Updated changelog. 2020-04-28 11:59:03 +02:00
Mark Paluch
cecd47d679 DATAMONGO-2529 - Ensure that MappingMongoConverter.read(…) is never called with null.
Previously, various methods attempted to pass a null argument as source for the converter. The API is non-null and implementations relying on these constraints were easily breakable.

We now make sure that the source is never null.
2020-04-23 15:25:45 +02:00
Mark Paluch
ed35e577af DATAMONGO-2504 - Polishing.
Update equals/hashCode implementation to use the Spring Data form. Make fields final where possible. Use diamond syntax. Reorder methods. Reformat code. Extend tests.

Original pull request: #848.
2020-04-23 15:25:45 +02:00
ddebray
f54cf40eda DATAMONGO-2504 - Add hashCode and equals to TextCriteria and Term.
Original pull request: #848.
2020-04-23 12:29:07 +02:00
Christoph Strobl
5314e6f8bb DATAMONGO-2513 - Fix Eq aggregation operator comparing collection values.
Original pull request: #855.
2020-04-22 11:47:02 +02:00
Mark Paluch
b7b2709177 DATAMONGO-2523 - Polishing.
Reformat code.

Original pull request: #859.
2020-04-22 10:08:33 +02:00
Christoph Strobl
34c47e84c0 DATAMONGO-2523 - Fix Json binding of SpEL expressions in arrays.
The closing bracket must not have a leading whitespace.

Original pull request: #859.
2020-04-22 10:08:30 +02:00
Mark Paluch
f7d91184a0 DATAMONGO-2517 - Polishing.
Reformat code.

Original pull request: #857.
2020-04-21 16:02:36 +02:00
Christoph Strobl
eeddc860f7 DATAMONGO-2517 - Fix invalid entity creation for text queries.
Fix a glitch in the MappingMongoConverter that uses the single String argument constructor (since it matches in type and parameter count to the given input string) to falsely instantiate an Entity when it should not.

Original pull request: #857.
2020-04-21 16:02:24 +02:00
Christoph Strobl
bcefdd209b DATAMONGO-2506 - Provide meaningful error message when using unsupported return type in repository aggregation method.
We improved the error message for unsupported return types instead of running into an IllegalArgumentException for unique results.

Original pull request: #851.
2020-04-07 14:59:30 +02:00
Mark Paluch
3f1fea2d19 DATAMONGO-2502 - Polishing.
Extend tests. Fix generics. Consistently use compiled patterns for positional placeholder removal.

Original pull request: #847.
2020-04-07 14:47:42 +02:00
Christoph Strobl
665322a69a DATAMONGO-2502 - Fix nested array path mapping for updates.
Original pull request: #847.
2020-04-07 14:17:05 +02:00
Mark Paluch
3e59bc3b38 DATAMONGO-2492 - Updated changelog. 2020-03-31 15:08:52 +02:00
Mark Paluch
1752931dde DATAMONGO-2485 - After release cleanups. 2020-03-25 10:58:27 +01:00
Mark Paluch
4b9bae1656 DATAMONGO-2485 - Prepare next development iteration. 2020-03-25 10:58:26 +01:00
Mark Paluch
74c08fa8aa DATAMONGO-2485 - Release version 2.2.6 (Moore SR6). 2020-03-25 10:46:02 +01:00
Mark Paluch
628aad8f64 DATAMONGO-2485 - Prepare 2.2.6 (Moore SR6). 2020-03-25 10:45:35 +01:00
Mark Paluch
39c8672e6d DATAMONGO-2485 - Updated changelog. 2020-03-25 10:45:28 +01:00
Christoph Strobl
620991ddee DATAMONGO-2300 - Polishing.
Move null check to event publishing logic.

Original Pull Request: #763
2020-03-23 10:11:41 +01:00
Heesu Jung
ba8f28f623 DATAMONGO-2300 - Add check rawType is null in readMap.
Original Pull Request: #763
2020-03-23 10:01:50 +01:00
Mark Paluch
6389055d3a DATAMONGO-2497 - Update documentation regarding @Transient properties usage in the persistence constructor. 2020-03-19 15:37:37 +01:00
Christoph Strobl
4465ed9819 DATAMONGO-2445 - Deprecate ReactiveGridFsOperations using AsyncInputStream.
Methods using AsyncInputStream will be removed in 3.0. Please use the ones accepting a Publisher.

Original pull request: #843.
2020-03-19 09:42:49 +01:00
Mark Paluch
8dc97e5d01 DATAMONGO-2488 - Polishing.
Simplify conditional entity check.

Original pull request: #841.
2020-03-11 14:38:17 +01:00
Christoph Strobl
a037c50961 DATAMONGO-2488 - Fix nested array path field name mapping.
Original pull request: #841.
2020-03-11 14:38:16 +01:00
Jens Schauder
28d5f02e15 DATAMONGO-2473 - Updated changelog. 2020-03-11 09:59:36 +01:00
Mark Paluch
e65a353fc4 DATAMONGO-2453 - After release cleanups. 2020-02-26 11:54:09 +01:00
Mark Paluch
42400e7836 DATAMONGO-2453 - Prepare next development iteration. 2020-02-26 11:54:08 +01:00
Mark Paluch
cdd7a2008b DATAMONGO-2453 - Release version 2.2.5 (Moore SR5). 2020-02-26 11:38:17 +01:00
Mark Paluch
c2b80fddd8 DATAMONGO-2453 - Prepare 2.2.5 (Moore SR5). 2020-02-26 11:37:58 +01:00
Mark Paluch
8eaa8119e6 DATAMONGO-2453 - Updated changelog. 2020-02-26 11:37:53 +01:00
Mark Paluch
5fccadd41e DATAMONGO-2452 - Updated changelog. 2020-02-26 11:31:49 +01:00
Christoph Strobl
5d0ab340e3 DATAMONGO-2478 - Fix NPE in Query.of when given a proxied source.
Original pull request: #836.
2020-02-24 11:34:36 +01:00
Christoph Strobl
5d7e9199de DATAMONGO-2476 - Fix Json parsing for unquoted placeholders in arrays.
Original pull request: #835.
2020-02-24 11:07:56 +01:00
Mark Paluch
5e2c65a650 DATAMONGO-2456 - Updated changelog. 2020-02-12 15:05:04 +01:00
Mark Paluch
1f5553d2d8 DATAMONGO-2079 - MappingMongoConverter no longer implements ValueResolver.
MappingMongoConverter no longer implements a package-private interface so that converter instances can be proxied.

Original Pull Request: #832
2020-02-04 14:52:43 +01:00
Mark Paluch
40d5ab050f DATAMONGO-2464 - Polishing.
Apply fix also to reactive MongoDB repository documentation.

Original pull request: #816.
2020-02-03 11:33:42 +01:00
LiangYong
1629ba11b2 DATAMONGO-2464 - Fix code examples in reference documentation.
fixed repository miss "{" issue.

Original pull request: #816.
2020-02-03 11:31:33 +01:00
Mark Paluch
6e94f138d5 DATAMONGO-2460 - Polishing.
Reformat code. Use diamond syntax.

Original pull request: #830.
2020-02-03 11:25:36 +01:00
Christoph Strobl
1b7273db42 DATAMONGO-2460 - Fix target type computation for complex id properties with @Field annotation.
We now set the target type to org.bson.Document for id properties annotated with @Field having the implicit target type derived from the annotation. Along the lines we fixed warn message when an id property with explicit (unsupported) field name is detected.

Original pull request: #830.
2020-02-03 11:25:36 +01:00
Mark Paluch
8857903831 DATAMONGO-2406 - Polishing.
Add optimization for Mono.

Original pull request: #825.
2020-01-29 09:58:14 +01:00
Christoph Strobl
69cacb5fe3 DATAMONGO-2406 - Derived reactive deleteBy query execution should allow Mono<Void> result.
Mono<Void> is now a supported return type of derived reactive deleteBy queries like:

    Mono<Void> deleteByLastname(String lastname);

Original pull request: #825.
2020-01-29 09:58:14 +01:00
Mark Paluch
ba4b958114 DATAMONGO-2457 - Polishing.
Slightly tweak wording.

Original pull request: #829.
2020-01-29 09:52:02 +01:00
Christoph Strobl
6d971ef2c8 DATAMONGO-2459 - Add sample for passing on limit and offset using reactive repositories.
Original pull request: #829.
2020-01-29 09:46:43 +01:00
Christoph Strobl
03ff37db92 DATAMONGO-2457 - Fix id type explanation in repository documentation.
Original pull request: #829.
2020-01-29 09:46:41 +01:00
Mark Paluch
428126ef75 DATAMONGO-2454 - Updated changelog. 2020-01-17 09:58:36 +01:00
Mark Paluch
aee242c52a DATAMONGO-2383 - Updated changelog. 2020-01-16 16:12:40 +01:00
Mark Paluch
1299f78e80 DATAMONGO-2432 - After release cleanups. 2020-01-15 12:48:23 +01:00
Mark Paluch
fc3d13d5bc DATAMONGO-2432 - Prepare next development iteration. 2020-01-15 12:48:22 +01:00
Mark Paluch
6d2f7b0c9e DATAMONGO-2432 - Release version 2.2.4 (Moore SR4). 2020-01-15 12:37:44 +01:00
Mark Paluch
84128cab28 DATAMONGO-2432 - Prepare 2.2.4 (Moore SR4). 2020-01-15 12:37:18 +01:00
Mark Paluch
8f2d2784f8 DATAMONGO-2432 - Updated changelog. 2020-01-15 12:37:09 +01:00
Christoph Strobl
37ee677a67 DATAMONGO-2451 - Fix value conversion for id properties used in sort expression.
Previously we falsely converted the sort value (1/-1) into the id types target value when a Field annotation had been present.

Original pull request: #822.
2020-01-15 11:52:06 +01:00
Mark Paluch
1729744a9e DATAMONGO-2431 - Updated changelog. 2020-01-15 10:36:38 +01:00
Mark Paluch
b59903c890 DATAMONGO-2450 - Polishing.
Replace stream with for-loop.

Original pull request: #820.
2020-01-15 10:15:23 +01:00
Christoph Strobl
5063e68562 DATAMONGO-2450 - Apply array filters to bulk write.
Original pull request: #820.
2020-01-15 10:15:23 +01:00
Christoph Strobl
3cbb572c7c DATAMONGO-2442 - Fix thenValueOf in $cond builder.
We now create a field reference when calling the builder instead of using the value as is.

Original pull request: #818.
2020-01-08 15:18:47 +01:00
Mark Paluch
bb4f11a239 DATAMONGO-2440 - Polishing.
Iterate over List instead of using the Stream API.

Original pull request: #817.
2020-01-08 15:18:47 +01:00
Christoph Strobl
8a1750691b DATAMONGO-2440 - Fix field target type conversion for collection values.
We now preserve the collection nature of the source type when applying custom target type conversions. Prior to this change collection values had been changed to single element causing query errors in MongoDB when using $in queries.

Original pull request: #817.
2020-01-08 15:18:47 +01:00
Christoph Strobl
5cffaf9d73 DATAMONGO-2423 - Polishing.
Update nullability annotations and reduce visibility in tests.

Original pull request: #815.
2020-01-08 13:25:07 +01:00
Christoph Strobl
a9e50b28df DATAMONGO-2423 - Nullability refinements for Update.
Ease non null restrictions for operators that may use null values like $set.

Original pull request: #815.
2020-01-08 13:24:50 +01:00
Mark Paluch
24512639fb DATAMONGO-2444 - Update copyright years to 2020. 2020-01-07 08:59:35 +01:00
Jens Schauder
1355d043b6 DATAMONGO-2422 - After release cleanups. 2019-12-04 14:29:17 +01:00
Jens Schauder
c7600ef9ed DATAMONGO-2422 - Prepare next development iteration. 2019-12-04 14:29:14 +01:00
Jens Schauder
a4cb0d6432 DATAMONGO-2422 - Release version 2.2.3 (Moore SR3). 2019-12-04 14:12:24 +01:00
Jens Schauder
437368bedb DATAMONGO-2422 - Prepare 2.2.3 (Moore SR3). 2019-12-04 14:11:44 +01:00
Jens Schauder
4057b193d6 DATAMONGO-2422 - Updated changelog. 2019-12-04 14:11:36 +01:00
Jens Schauder
89b1b5c7f6 DATAMONGO-2421 - Updated changelog. 2019-12-04 12:09:48 +01:00
Mark Paluch
60d3438277 DATAMONGO-2430 - Upgrade to mongo-java-driver 3.11.2. 2019-12-04 11:42:04 +01:00
Mark Paluch
a578a10b5b DATAMONGO-2418 - Polishing.
Reformat code.

Original pull request: #814.
2019-12-04 10:31:33 +01:00
Christoph Strobl
5cf24af00b DATAMONGO-2418 - Obtain EvaluationContextExtensions lazily when parsing Bson queries.
An eager evaluation of the context extension can lead to errors when e.g. the security context was not present.

Original pull request: #814.
2019-12-04 10:31:33 +01:00
Mark Paluch
6c0e455146 DATAMONGO-2410 - Polishing.
Simplify cast. Extend test with DBObject interface.

Original pull request: #813.
2019-12-04 08:56:54 +01:00
Christoph Strobl
932a946868 DATAMONGO-2410 - Fix Document to BasicDBObject conversion.
Original pull request: #813.
2019-12-04 08:56:54 +01:00
Mark Paluch
99a1cfbff9 DATAMONGO-2402 - After release cleanups. 2019-11-18 12:42:05 +01:00
Mark Paluch
d7bbdde1e7 DATAMONGO-2402 - Prepare next development iteration. 2019-11-18 12:42:04 +01:00
Mark Paluch
7dba98dce8 DATAMONGO-2402 - Release version 2.2.2 (Moore SR2). 2019-11-18 12:32:12 +01:00
Mark Paluch
c1ae30bd82 DATAMONGO-2402 - Prepare 2.2.2 (Moore SR2). 2019-11-18 12:31:53 +01:00
Mark Paluch
6aa5aea424 DATAMONGO-2402 - Updated changelog. 2019-11-18 12:31:44 +01:00
Mark Paluch
bc1b00813c DATAMONGO-2401 - Updated changelog. 2019-11-18 12:16:28 +01:00
Mark Paluch
d1ad3ab301 DATAMONGO-2414 - Polishing.
Use longer timeout to cater for slower CI environments.

Original Pull Request: #807
2019-11-14 11:54:43 +01:00
Mark Paluch
923134bbdc DATAMONGO-2414 - Guard drain loop in AsyncInputStreamHandler with state switch.
We now use a non-blocking state switch to determine whether to invoke drainLoop(…) from Subscriber completion.

Previously, we relied on same thread identification assuming if the subscription thread and the completion thread were the same, that we're already running inside the drain loop.
It turns out that a I/O thread could also run in event-loop mode where subscription and completion happens on the same thread but in between there's some processing and so the the call to completion is a delayed signal and not being called on the same stack as drainLoop(…).
The same-thread assumption was in place to avoid StackOverflow caused by infinite recursions.

We now use a state lock to enter the drain loop. Any concurrent attempts to re-enter the drain loop in Subscriber completion is now prevented to make sure that we continue draining while not causing stack recursions.

Original Pull Request: #807
2019-11-14 11:54:30 +01:00
Mark Paluch
e211f69df5 DATAMONGO-2409 - Polishing.
Adapt also ExecutableFindOperation.DistinctWithProjection.asType() to return the appropriate TerminatingDistinct.

Original pull request: #805.
2019-11-11 10:22:37 +01:00
Christoph Strobl
fc35d706a0 DATAMONGO-2409 - Fix return type of Kotlin extension function for ReactiveFindOperation.DistinctWithProjection.asType().
Original pull request: #805.
2019-11-11 10:22:37 +01:00
Mark Paluch
82894e6aff DATAMONGO-2403 - Polishing.
Use handle(…) to skip values instead of flatMap(…) to reduce overhead.

Original pull request: #804.
2019-11-08 13:51:20 +01:00
Christoph Strobl
7356f157bb DATAMONGO-2403 - Fix aggregation simple type result retrieval from empty document.
Projections used within an aggregation pipeline can result in empty documents emitted by the driver. We now guarded those cases and skip those documents within a Flux or simply return an empty Mono depending on the methods signature.

Original pull request: #804.
2019-11-08 13:48:10 +01:00
Christoph Strobl
783fc6268a DATAMONGO-2382 - After release cleanups. 2019-11-04 15:34:27 +01:00
Christoph Strobl
360b17f299 DATAMONGO-2382 - Prepare next development iteration. 2019-11-04 15:34:26 +01:00
Christoph Strobl
2cfcdaff7c DATAMONGO-2382 - Release version 2.2.1 (Moore SR1). 2019-11-04 14:55:02 +01:00
Christoph Strobl
9d9cf46e47 DATAMONGO-2382 - Prepare 2.2.1 (Moore SR1). 2019-11-04 14:54:16 +01:00
Christoph Strobl
98661cf9a2 DATAMONGO-2382 - Updated changelog. 2019-11-04 14:54:10 +01:00
Christoph Strobl
cc50cd5e3a DATAMONGO-2381 - Updated changelog. 2019-11-04 10:34:52 +01:00
Christoph Strobl
d8399d2d23 DATAMONGO-2393 - Remove capturing lambdas and extract methods.
Original Pull Request: #799
2019-10-31 12:57:06 +01:00
Mark Paluch
f2134fb2f8 DATAMONGO-2393 - Support configurable chunk size.
We now allow consuming GridFS files using a configurable chunk size. The default chunk size is now 256kb.

Original Pull Request: #799
2019-10-31 12:56:59 +01:00
Mark Paluch
ec3ccc004e DATAMONGO-2393 - Polishing.
Extract read requests into inner class.

Original Pull Request: #799
2019-10-31 12:56:50 +01:00
Mark Paluch
6cb246c18a DATAMONGO-2393 - Fix BufferOverflow in GridFS upload.
AsyncInputStreamAdapter now properly splits and buffers incoming DataBuffers according the read requests of AsyncInputStream.read(…) calls.
Previously, the adapter used the input buffer size to be used as the output buffer size. A larger DataBuffer than the transfer buffer handed in through read(…) caused a BufferOverflow.

Original Pull Request: #799
2019-10-31 12:56:42 +01:00
Mark Paluch
e73cea0ecf DATAMONGO-2393 - Use drain loop for same-thread processing in GridFS download stream.
We now rely on an outer drain-loop when GridFS reads complete on the same thread instead of using recursive subscriptions to avoid StackOverflow. Previously, we recursively invoked subscriptions that lead to an increased stack size.

Original Pull Request: #799
2019-10-31 12:56:28 +01:00
Christoph Strobl
c69e185a2a DATAMONGO-2399 - Upgrade to MongoDB Java Driver 3.11.1 2019-10-30 10:49:43 +01:00
Mark Paluch
5789f59222 DATAMONGO-2388 - Polishing.
Use StringJoiner to create comma-delimited String. Add nullability annotations.

Original pull request: #797.
2019-10-28 10:55:58 +01:00
Christoph Strobl
5178eeb340 DATAMONGO-2388 - Fix CodecConfigurationException when reading index info that contains DbRef.
Provide the default CodecRegistry when converting partial index data to its String representation used in IndexInfo.

Original pull request: #797.
2019-10-28 10:47:57 +01:00
Mark Paluch
bc5e7fa4a2 DATAMONGO-2394 - Polishing.
Reformat code.

Original pull request: #798.
2019-10-28 09:32:14 +01:00
Christoph Strobl
c28ace6d40 DATAMONGO-2394 - Fix distance conversion for derived finder using near along with GeoJSON.
GeoJson requries the distance to be in meters instead of radians, so we now make sure to convert it correctly

Original pull request: #798.
2019-10-28 09:32:10 +01:00
Mark Paluch
de4fae37e1 DATAMONGO-2392 - Polishing.
Add author tags. Move integration tests to existing test class.
Apply more appropriate in existing tests assertions. Use diamond syntax.

Original pull request: #796.
2019-10-16 13:55:12 +02:00
Mark Paluch
2f1aff3ec3 DATAMONGO-2392 - Consistently use GridFS file Id instead of ObjectId.
We now consistently use GridFSFile.getId() to allow custom Id usage instead of enforcing the Id to be an ObjectId. Using the native Id allows interaction with files that use a custom Id type.

Original pull request: #796.
2019-10-16 13:55:12 +02:00
Nick Stolwijk
6970f934bd DATAMONGO-2392 - Fix handling in ReactiveGridFsTemplate of GridFS files with custom id type.
Original pull request: #796.
2019-10-16 13:55:12 +02:00
Greg Turnquist
6b5168e102 DATAMONGO-2334 - Create CI job. 2019-09-30 14:36:06 -05:00
Mark Paluch
4420edb4dc DATAMONGO-2334 - After release cleanups. 2019-09-30 16:17:54 +02:00
Mark Paluch
c2fae95fee DATAMONGO-2334 - Prepare next development iteration. 2019-09-30 16:17:53 +02:00
289 changed files with 3519 additions and 6185 deletions

View File

@@ -1,38 +0,0 @@
language: java
jdk:
- oraclejdk8
before_install:
- mkdir -p downloads
- mkdir -p var/db var/log
- if [[ ! -d downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION} ]] ; then cd downloads && wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}.tgz && tar xzf mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}.tgz && cd ..; fi
- downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongod --version
- downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongod --dbpath var/db --replSet rs0 --fork --logpath var/log/mongod.log
- sleep 10
- |-
downloads/mongodb-linux-x86_64-ubuntu1604-${MONGO_VERSION}/bin/mongo --eval "rs.initiate({_id: 'rs0', members:[{_id: 0, host: '127.0.0.1:27017'}]});"
sleep 15
env:
matrix:
- MONGO_VERSION=4.1.10
- MONGO_VERSION=4.0.4
- MONGO_VERSION=3.6.12
- MONGO_VERSION=3.4.20
global:
- PROFILE=ci
addons:
apt:
packages:
- oracle-java8-installer
sudo: false
cache:
directories:
- $HOME/.m2
- downloads
script: "mvn clean dependency:list test -P${PROFILE} -Dsort"

10
Jenkinsfile vendored
View File

@@ -3,7 +3,7 @@ pipeline {
triggers {
pollSCM 'H/10 * * * *'
upstream(upstreamProjects: "spring-data-commons/master", threshold: hudson.model.Result.SUCCESS)
upstream(upstreamProjects: "spring-data-commons/2.2.x", threshold: hudson.model.Result.SUCCESS)
}
options {
@@ -68,7 +68,7 @@ pipeline {
stage("test: baseline") {
when {
anyOf {
branch 'master'
branch '2.2.x'
not { triggeredBy 'UpstreamCause' }
}
}
@@ -94,7 +94,7 @@ pipeline {
stage("Test other configurations") {
when {
anyOf {
branch 'master'
branch '2.2.x'
not { triggeredBy 'UpstreamCause' }
}
}
@@ -143,7 +143,7 @@ pipeline {
stage('Release to artifactory') {
when {
anyOf {
branch 'master'
branch '2.2.x'
not { triggeredBy 'UpstreamCause' }
}
}
@@ -175,7 +175,7 @@ pipeline {
stage('Publish documentation') {
when {
branch 'master'
branch '2.2.x'
}
agent {
docker {

14
pom.xml
View File

@@ -5,7 +5,7 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.0.0.M2</version>
<version>2.2.11.RELEASE</version>
<packaging>pom</packaging>
<name>Spring Data MongoDB</name>
@@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.3.0.M2</version>
<version>2.2.11.RELEASE</version>
</parent>
<modules>
@@ -26,9 +26,9 @@
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-mongodb</dist.id>
<springdata.commons>2.3.0.M2</springdata.commons>
<mongo>3.12.0</mongo>
<mongo.reactivestreams>1.13.0</mongo.reactivestreams>
<springdata.commons>2.2.11.RELEASE</springdata.commons>
<mongo>3.11.2</mongo>
<mongo.reactivestreams>1.12.0</mongo.reactivestreams>
<jmh.version>1.19</jmh.version>
</properties>
@@ -134,8 +134,8 @@
<repositories>
<repository>
<id>spring-libs-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
<id>spring-libs-release</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.0.0.M2</version>
<version>2.2.11.RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.0.0.M2</version>
<version>2.2.11.RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>3.0.0.M2</version>
<version>2.2.11.RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -25,8 +25,10 @@ public class LazyLoadingException extends UncategorizedDataAccessException {
private static final long serialVersionUID = -7089224903873220037L;
/**
* @param msg
* @param cause
* Constructor for LazyLoadingException.
*
* @param msg the detail message.
* @param cause the exception thrown by underlying data access API.
*/
public LazyLoadingException(String msg, Throwable cause) {
super(msg, cause);

View File

@@ -79,7 +79,7 @@ public class MongoDatabaseUtils {
* @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from.
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
*/
public static MongoDatabase getDatabase(String dbName, MongoDbFactory factory) {
public static MongoDatabase getDatabase(@Nullable String dbName, MongoDbFactory factory) {
return doGetMongoDatabase(dbName, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION);
}
@@ -88,13 +88,13 @@ public class MongoDatabaseUtils {
* <p />
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the current
* {@link Thread} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
*
*
* @param dbName the name of the {@link MongoDatabase} to get.
* @param factory the {@link MongoDbFactory} to get the {@link MongoDatabase} from.
* @param sessionSynchronization the synchronization to use. Must not be {@literal null}.
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
*/
public static MongoDatabase getDatabase(String dbName, MongoDbFactory factory,
public static MongoDatabase getDatabase(@Nullable String dbName, MongoDbFactory factory,
SessionSynchronization sessionSynchronization) {
return doGetMongoDatabase(dbName, factory, sessionSynchronization);
}

View File

@@ -37,7 +37,7 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi
/**
* Creates a default {@link MongoDatabase} instance.
*
* @return
* @return never {@literal null}.
* @throws DataAccessException
*/
MongoDatabase getDb() throws DataAccessException;
@@ -46,7 +46,7 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi
* Creates a {@link DB} instance to access the database with the given name.
*
* @param dbName must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
* @throws DataAccessException
*/
MongoDatabase getDb(String dbName) throws DataAccessException;

View File

@@ -38,7 +38,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider {
/**
* Creates a default {@link MongoDatabase} instance.
*
* @return
* @return never {@literal null}.
* @throws DataAccessException
*/
MongoDatabase getMongoDatabase() throws DataAccessException;
@@ -47,7 +47,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider {
* Creates a {@link MongoDatabase} instance to access the database with the given name.
*
* @param dbName must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
* @throws DataAccessException
*/
MongoDatabase getMongoDatabase(String dbName) throws DataAccessException;

View File

@@ -42,21 +42,21 @@ public @interface EnableMongoAuditing {
/**
* Configures the {@link AuditorAware} bean to be used to lookup the current principal.
*
* @return
* @return empty {@link String} by default.
*/
String auditorAwareRef() default "";
/**
* Configures whether the creation and modification dates are set. Defaults to {@literal true}.
*
* @return
* @return {@literal true} by default.
*/
boolean setDates() default true;
/**
* Configures whether the entity shall be marked as modified on creation. Defaults to {@literal true}.
*
* @return
* @return {@literal true} by default.
*/
boolean modifyOnCreate() default true;
@@ -64,7 +64,7 @@ public @interface EnableMongoAuditing {
* Configures a {@link DateTimeProvider} bean name that allows customizing the {@link org.joda.time.DateTime} to be
* used for setting creation and modification dates.
*
* @return
* @return empty {@link String} by default.
*/
String dateTimeProviderRef() default "";
}

View File

@@ -89,7 +89,7 @@ public abstract class MongoConfigurationSupport {
/**
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
* {@link #mongoMappingContext()}. Returns an empty {@link MongoCustomConversions} instance by default.
* {@link MongoMappingContext}. Returns an empty {@link MongoCustomConversions} instance by default.
*
* @return must not be {@literal null}.
*/

View File

@@ -94,7 +94,6 @@ public interface BulkOperations {
* Add a list of updates to the bulk operation. For each update request, all matching documents are updated.
*
* @param updates Update operations to perform.
* @return The bulk operation.
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
*/
BulkOperations updateMulti(List<Pair<Query, Update>> updates);
@@ -105,7 +104,6 @@ public interface BulkOperations {
*
* @param query Update criteria.
* @param update Update operation to perform.
* @return The bulk operation.
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
*/
BulkOperations upsert(Query query, Update update);
@@ -115,7 +113,6 @@ public interface BulkOperations {
* else an insert.
*
* @param updates Updates/insert operations to perform.
* @return The bulk operation.
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
*/
BulkOperations upsert(List<Pair<Query, Update>> updates);

View File

@@ -29,7 +29,7 @@ import com.mongodb.client.MongoCollection;
* @author Grame Rocher
* @author Oliver Gierke
* @author John Brisbin
* @auhtor Christoph Strobl
* @author Christoph Strobl
* @since 1.0
*/
public interface CollectionCallback<T> {

View File

@@ -95,7 +95,7 @@ public class CollectionOptions {
/**
* Create new {@link CollectionOptions} with already given settings and capped set to {@literal true}. <br />
* <strong>NOTE</strong> Using capped collections requires defining {@link #size(int)}.
* <strong>NOTE</strong> Using capped collections requires defining {@link #size(long)}.
*
* @return new {@link CollectionOptions}.
* @since 2.0

View File

@@ -1,227 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.data.mongodb.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.bson.Document;
import org.springframework.data.geo.Point;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
* Value object representing a count query. Count queries using {@code $near} or {@code $nearSphere} require a rewrite
* to {@code $geoWithin}.
*
* @author Christoph Strobl
* @author Mark Paluch
* @since 3.0
*/
class CountQuery {
private Document source;
private CountQuery(Document source) {
this.source = source;
}
public static CountQuery of(Document source) {
return new CountQuery(source);
}
/**
* Returns the query {@link Document} that can be used with {@code countDocuments()}. Potentially rewrites the query
* to be usable with {@code countDocuments()}.
*
* @return the query {@link Document} that can be used with {@code countDocuments()}.
*/
public Document toQueryDocument() {
if (!requiresRewrite(source)) {
return source;
}
Document target = new Document();
for (Map.Entry<String, Object> entry : source.entrySet()) {
if (entry.getValue() instanceof Document && requiresRewrite(entry.getValue())) {
Document theValue = (Document) entry.getValue();
target.putAll(createGeoWithin(entry.getKey(), theValue, source.get("$and")));
continue;
}
if (entry.getValue() instanceof Collection && requiresRewrite(entry.getValue())) {
Collection<?> source = (Collection<?>) entry.getValue();
target.put(entry.getKey(), rewriteCollection(source));
continue;
}
if ("$and".equals(entry.getKey()) && target.containsKey("$and")) {
// Expect $and to be processed with Document and createGeoWithin.
continue;
}
target.put(entry.getKey(), entry.getValue());
}
return target;
}
/**
* @param valueToInspect
* @return {@code true} if the enclosing element needs to be rewritten.
*/
private boolean requiresRewrite(Object valueToInspect) {
if (valueToInspect instanceof Document) {
return requiresRewrite((Document) valueToInspect);
}
if (valueToInspect instanceof Collection) {
return requiresRewrite((Collection) valueToInspect);
}
return false;
}
private boolean requiresRewrite(Collection<?> collection) {
for (Object o : collection) {
if (o instanceof Document && requiresRewrite((Document) o)) {
return true;
}
}
return false;
}
private boolean requiresRewrite(Document document) {
if (containsNear(document)) {
return true;
}
for (Object entry : document.values()) {
if (requiresRewrite(entry)) {
return true;
}
}
return false;
}
private Collection<Object> rewriteCollection(Collection<?> source) {
Collection<Object> rewrittenCollection = new ArrayList<>(source.size());
for (Object item : source) {
if (item instanceof Document && requiresRewrite(item)) {
rewrittenCollection.add(CountQuery.of((Document) item).toQueryDocument());
} else {
rewrittenCollection.add(item);
}
}
return rewrittenCollection;
}
/**
* Rewrite the near query for field {@code key} to {@code $geoWithin}.
*
* @param key the queried field.
* @param source source {@link Document}.
* @param $and potentially existing {@code $and} condition.
* @return the rewritten query {@link Document}.
*/
private static Document createGeoWithin(String key, Document source, @Nullable Object $and) {
boolean spheric = source.containsKey("$nearSphere");
Object $near = spheric ? source.get("$nearSphere") : source.get("$near");
Number maxDistance = source.containsKey("$maxDistance") ? (Number) source.get("$maxDistance") : Double.MAX_VALUE;
List<Object> $centerMax = Arrays.asList(toCenterCoordinates($near), maxDistance);
Document $geoWithinMax = new Document("$geoWithin",
new Document(spheric ? "$centerSphere" : "$center", $centerMax));
if (!containsNearWithMinDistance(source)) {
return new Document(key, $geoWithinMax);
}
Number minDistance = (Number) source.get("$minDistance");
List<Object> $centerMin = Arrays.asList(toCenterCoordinates($near), minDistance);
Document $geoWithinMin = new Document("$geoWithin",
new Document(spheric ? "$centerSphere" : "$center", $centerMin));
List<Document> criteria = new ArrayList<>();
if ($and != null) {
if ($and instanceof Collection) {
criteria.addAll((Collection) $and);
} else {
throw new IllegalArgumentException(
"Cannot rewrite query as it contains an '$and' element that is not a Collection!: Offending element: "
+ $and);
}
}
criteria.add(new Document("$nor", Collections.singletonList(new Document(key, $geoWithinMin))));
criteria.add(new Document(key, $geoWithinMax));
return new Document("$and", criteria);
}
private static boolean containsNear(Document source) {
return source.containsKey("$near") || source.containsKey("$nearSphere");
}
private static boolean containsNearWithMinDistance(Document source) {
if (!containsNear(source)) {
return false;
}
return source.containsKey("$minDistance");
}
private static Object toCenterCoordinates(Object value) {
if (ObjectUtils.isArray(value)) {
return value;
}
if (value instanceof Point) {
return Arrays.asList(((Point) value).getX(), ((Point) value).getY());
}
if (value instanceof Document && ((Document) value).containsKey("x")) {
Document point = (Document) value;
return Arrays.asList(point.get("x"), point.get("y"));
}
return value;
}
}

View File

@@ -43,9 +43,10 @@ public interface CursorPreparer extends ReadPreferenceAware {
/**
* Prepare the given cursor (apply limits, skips and so on). Returns the prepared cursor.
*
* @param cursor
* @param iterable must not be {@literal null}.
* @return never {@literal null}.
*/
FindIterable<Document> prepare(FindIterable<Document> cursor);
FindIterable<Document> prepare(FindIterable<Document> iterable);
/**
* Apply query specific settings to {@link MongoCollection} and initate a find operation returning a
@@ -53,7 +54,7 @@ public interface CursorPreparer extends ReadPreferenceAware {
*
* @param collection must not be {@literal null}.
* @param find must not be {@literal null}.
* @return
* @return never {@literal null}.
* @throws IllegalArgumentException if one of the required arguments is {@literal null}.
* @since 2.2
*/

View File

@@ -23,7 +23,7 @@ import com.mongodb.MongoException;
/**
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document
* basis. Implementations of this interface perform the actual work of prcoessing each document but don't need to worry
* about exception handling. {@MongoException}s will be caught and translated by the calling MongoTemplate An
* about exception handling. {@link MongoException}s will be caught and translated by the calling MongoTemplate An
* DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later for
* later inspection.
*

View File

@@ -66,7 +66,7 @@ class EntityOperations {
* Creates a new {@link Entity} for the given bean.
*
* @param entity must not be {@literal null}.
* @return
* @return new instance of {@link Entity}.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> Entity<T> forEntity(T entity) {
@@ -89,7 +89,7 @@ class EntityOperations {
*
* @param entity must not be {@literal null}.
* @param conversionService must not be {@literal null}.
* @return
* @return new instance of {@link AdaptibleEntity}.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> AdaptibleEntity<T> forEntity(T entity, ConversionService conversionService) {
@@ -108,6 +108,10 @@ class EntityOperations {
return AdaptibleMappedEntity.of(entity, context, conversionService);
}
/**
* @param entityClass should not be null.
* @return the {@link MongoPersistentEntity#getCollection() collection name}.
*/
public String determineCollectionName(@Nullable Class<?> entityClass) {
if (entityClass == null) {
@@ -138,7 +142,7 @@ class EntityOperations {
* {@code _id} if no identifier property can be found.
*
* @param type must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
public String getIdPropertyName(Class<?> type) {

View File

@@ -88,10 +88,10 @@ public interface ExecutableAggregationOperation {
/**
* Apply pipeline operations as specified and stream all matching elements. <br />
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.Cursor}
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable}
*
* @return a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.Cursor} that needs to be closed.
* Never {@literal null}.
* @return a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs
* to be closed. Never {@literal null}.
*/
CloseableIterator<T> stream();
}

View File

@@ -117,8 +117,8 @@ public interface ExecutableFindOperation {
/**
* Stream all matching elements.
*
* @return a {@link Stream} that wraps the a Mongo DB {@link com.mongodb.Cursor} that needs to be closed. Never
* {@literal null}.
* @return a {@link Stream} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs to be
* closed. Never {@literal null}.
*/
Stream<T> stream();

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.data.mongodb.core;
import com.mongodb.ReadPreference;
import lombok.AccessLevel;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@@ -26,6 +25,7 @@ import java.util.Optional;
import java.util.stream.Stream;
import org.bson.Document;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
@@ -37,6 +37,7 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import com.mongodb.ReadPreference;
import com.mongodb.client.FindIterable;
/**
@@ -257,9 +258,9 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
* @see org.springframework.data.mongodb.core.CursorPreparer#prepare(com.mongodb.clientFindIterable)
*/
@Override
public FindIterable<Document> prepare(FindIterable<Document> cursor) {
public FindIterable<Document> prepare(FindIterable<Document> iterable) {
FindIterable<Document> target = delegate != null ? delegate.prepare(cursor) : cursor;
FindIterable<Document> target = delegate != null ? delegate.prepare(iterable) : iterable;
return limit.map(target::limit).orElse(target);
}

View File

@@ -17,10 +17,8 @@ package org.springframework.data.mongodb.core;
import java.util.Optional;
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.lang.Nullable;
import com.mongodb.client.result.UpdateResult;
@@ -153,16 +151,13 @@ public interface ExecutableUpdateOperation {
interface UpdateWithUpdate<T> {
/**
* Set the {@link UpdateDefinition} to be applied.
* Set the {@link Update} to be applied.
*
* @param update must not be {@literal null}.
* @return new instance of {@link TerminatingUpdate}.
* @throws IllegalArgumentException if update is {@literal null}.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
TerminatingUpdate<T> apply(UpdateDefinition update);
TerminatingUpdate<T> apply(Update update);
/**
* Specify {@code replacement} object.

View File

@@ -21,7 +21,7 @@ import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -67,7 +67,7 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
@NonNull MongoTemplate template;
@NonNull Class domainType;
Query query;
@Nullable UpdateDefinition update;
@Nullable Update update;
@Nullable String collection;
@Nullable FindAndModifyOptions findAndModifyOptions;
@Nullable FindAndReplaceOptions findAndReplaceOptions;
@@ -76,10 +76,10 @@ class ExecutableUpdateOperationSupport implements ExecutableUpdateOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.UpdateWithUpdate#apply(org.springframework.data.mongodb.core.query.UpdateDefinition)
* @see org.springframework.data.mongodb.core.ExecutableUpdateOperation.UpdateWithUpdate#apply(Update)
*/
@Override
public TerminatingUpdate<T> apply(UpdateDefinition update) {
public TerminatingUpdate<T> apply(Update update) {
Assert.notNull(update, "Update must not be null!");

View File

@@ -78,7 +78,7 @@ public class FindAndModifyOptions {
}
/**
* Create new {@link FindAndModifyOptions} based on option of given {@litearl source}.
* Create new {@link FindAndModifyOptions} based on option of given {@literal source}.
*
* @param source can be {@literal null}.
* @return new instance of {@link FindAndModifyOptions}.
@@ -117,8 +117,8 @@ public class FindAndModifyOptions {
/**
* Define the {@link Collation} specifying language-specific rules for string comparison.
*
* @param collation
* @return
* @param collation can be {@literal null}.
* @return this.
* @since 2.0
*/
public FindAndModifyOptions collation(@Nullable Collation collation) {
@@ -142,7 +142,7 @@ public class FindAndModifyOptions {
/**
* Get the {@link Collation} specifying language-specific rules for string comparison.
*
* @return
* @return never {@literal null}.
* @since 2.0
*/
public Optional<Collation> getCollation() {

View File

@@ -116,7 +116,7 @@ public class FindAndReplaceOptions {
/**
* Get the bit indicating to return the replacement document.
*
* @return
* @return {@literal true} if set.
*/
public boolean isReturnNew() {
return returnNew;
@@ -125,7 +125,7 @@ public class FindAndReplaceOptions {
/**
* Get the bit indicating if to create a new document if not exists.
*
* @return
* @return {@literal true} if set.
*/
public boolean isUpsert() {
return upsert;

View File

@@ -54,7 +54,7 @@ public interface FindPublisherPreparer extends ReadPreferenceAware {
*
* @param collection must not be {@literal null}.
* @param find must not be {@literal null}.
* @return
* @return never {@literal null}.
* @throws IllegalArgumentException if one of the required arguments is {@literal null}.
* @since 2.2
*/

View File

@@ -47,7 +47,7 @@ class GeoCommandStatistics {
* Creates a new {@link GeoCommandStatistics} from the given command result extracting the statistics.
*
* @param commandResult must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
public static GeoCommandStatistics from(Document commandResult) {
@@ -61,7 +61,7 @@ class GeoCommandStatistics {
* Returns the average distance reported by the command result. Mitigating a removal of the field in case the command
* didn't return any result introduced in MongoDB 3.2 RC1.
*
* @return
* @return never {@literal null}, uses {@link Double#NaN} if {@literal avgDistance} does not exist.
* @see <a href="https://jira.mongodb.org/browse/SERVER-21024">MongoDB Jira SERVER-21024</a>
*/
public double getAverageDistance() {

View File

@@ -265,7 +265,7 @@ public abstract class MongoDbFactorySupport<C> implements MongoDbFactory {
factory.addAdvice(new SessionAwareMethodInterceptor<>(session, target, ClientSession.class, MongoDatabase.class,
this::proxyDatabase, MongoCollection.class, this::proxyCollection));
return targetType.cast(factory.getProxy());
return targetType.cast(factory.getProxy(target.getClass().getClassLoader()));
}
}

View File

@@ -27,7 +27,6 @@ import org.springframework.data.mongodb.core.BulkOperations.BulkMode;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
@@ -41,7 +40,6 @@ import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.util.CloseableIterator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -59,7 +57,7 @@ import com.mongodb.client.result.UpdateResult;
* Interface that specifies a basic set of MongoDB operations. Implemented by {@link MongoTemplate}. Not often used but
* a useful option for extensibility and testability (as it can be easily mocked, stubbed, or be the target of a JDK
* proxy).
* <p/>
* <p />
* <strong>NOTE:</strong> Some operations cannot be executed within a MongoDB transaction. Please refer to the MongoDB
* specific documentation to learn more about <a href="https://docs.mongodb.com/manual/core/transactions/">Multi
* Document Transactions</a>.
@@ -80,7 +78,7 @@ public interface MongoOperations extends FluentMongoOperations {
* The collection name used for the specified class by this template.
*
* @param entityClass must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
String getCollectionName(Class<?> entityClass);
@@ -177,7 +175,7 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Obtain a {@link ClientSession session} bound instance of {@link SessionScoped} binding the {@link ClientSession}
* provided by the given {@link Supplier} to each and every command issued against MongoDB.
* <p/>
* <p />
* <strong>Note:</strong> It is up to the caller to manage the {@link ClientSession} lifecycle. Use the
* {@link SessionScoped#execute(SessionCallback, Consumer)} hook to potentially close the {@link ClientSession}.
*
@@ -213,7 +211,7 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Obtain a {@link ClientSession} bound instance of {@link MongoOperations}.
* <p/>
* <p />
* <strong>Note:</strong> It is up to the caller to manage the {@link ClientSession} lifecycle.
*
* @param session must not be {@literal null}.
@@ -362,7 +360,7 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.DB} level.
*
* @return
* @return never {@literal null}.
* @since 1.7
* @deprecated since 2.2. The {@code eval} command has been removed without replacement in MongoDB Server 4.2.0.
*/
@@ -885,15 +883,12 @@ public interface MongoOperations extends FluentMongoOperations {
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
* @return the converted object that was updated before it was updated or {@literal null}, if not found.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
@Nullable
<T> T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass);
<T> T findAndModify(Query query, Update update, Class<T> entityClass);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
@@ -901,16 +896,13 @@ public interface MongoOperations extends FluentMongoOperations {
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
* @param collectionName the collection to query. Must not be {@literal null}.
* @return the converted object that was updated before it was updated or {@literal null}, if not found.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
@Nullable
<T> T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass, String collectionName);
<T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
@@ -919,18 +911,15 @@ public interface MongoOperations extends FluentMongoOperations {
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification.
* @param update the {@link UpdateDefinition} to apply on matching documents.
* @param update the {@link Update} to apply on matching documents.
* @param options the {@link FindAndModifyOptions} holding additional information.
* @param entityClass the parametrized type.
* @return the converted object that was updated or {@literal null}, if not found. Depending on the value of
* {@link FindAndModifyOptions#isReturnNew()} this will either be the object as it was before the update or as
* it is after the update.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
@Nullable
<T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass);
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify <a/>
@@ -939,19 +928,16 @@ public interface MongoOperations extends FluentMongoOperations {
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
* @param collectionName the collection to query. Must not be {@literal null}.
* @return the converted object that was updated or {@literal null}, if not found. Depending on the value of
* {@link FindAndModifyOptions#isReturnNew()} this will either be the object as it was before the update or as
* it is after the update.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
@Nullable
<T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass,
<T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName);
/**
@@ -1300,112 +1286,99 @@ public interface MongoOperations extends FluentMongoOperations {
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document. <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, UpdateDefinition, FindAndModifyOptions, Class, String)} instead.
* Use {@link #findAndModify(Query, Update, FindAndModifyOptions, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be upserted. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing object. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object. Must not be {@literal null}.
* @param entityClass class that determines the collection to use. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult upsert(Query query, UpdateDefinition update, Class<?> entityClass);
UpdateResult upsert(Query query, Update update, Class<?> entityClass);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #upsert(Query, UpdateDefinition, Class, String)} to get full type specific
* support. <br />
* domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support.
* <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, UpdateDefinition, FindAndModifyOptions, Class, String)} instead.
* Use {@link #findAndModify(Query, Update, FindAndModifyOptions, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be upserted. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing object. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult upsert(Query query, UpdateDefinition update, String collectionName);
UpdateResult upsert(Query query, Update update, String collectionName);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document.
*
* combining the query document and the update document. <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, Update, FindAndModifyOptions, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be upserted. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing object. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object. Must not be {@literal null}.
* @param entityClass class of the pojo to be operated on. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult upsert(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName);
UpdateResult upsert(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Updates the first object that is found in the collection of the entity class that matches the query document with
* the provided update document.
* the provided update document. <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, Update, Class)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param entityClass class that determines the collection to use.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult updateFirst(Query query, UpdateDefinition update, Class<?> entityClass);
UpdateResult updateFirst(Query query, Update update, Class<?> entityClass);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #updateFirst(Query, UpdateDefinition, Class, String)} to get full type specific
* support.
* domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support.
* <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, Update, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult updateFirst(Query query, UpdateDefinition update, String collectionName);
UpdateResult updateFirst(Query query, Update update, String collectionName);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document. <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, Update, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param entityClass class of the pojo to be operated on. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult updateFirst(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName);
UpdateResult updateFirst(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
@@ -1413,34 +1386,27 @@ public interface MongoOperations extends FluentMongoOperations {
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param entityClass class of the pojo to be operated on. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult updateMulti(Query query, UpdateDefinition update, Class<?> entityClass);
UpdateResult updateMulti(Query query, Update update, Class<?> entityClass);
/**
* Updates all objects that are found in the specified collection that matches the query document criteria with the
* provided updated document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #updateMulti(Query, UpdateDefinition, Class, String)} to get full type specific
* support.
* domain type information. Use {@link #updateMulti(Query, Update, Class, String)} to get full type specific support.
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult updateMulti(Query query, UpdateDefinition update, String collectionName);
UpdateResult updateMulti(Query query, Update update, String collectionName);
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
@@ -1448,16 +1414,13 @@ public interface MongoOperations extends FluentMongoOperations {
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param entityClass class of the pojo to be operated on. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
UpdateResult updateMulti(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName);
UpdateResult updateMulti(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Remove the given object from the collection by {@literal id} and (if applicable) its
@@ -1557,7 +1520,7 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Returns the underlying {@link MongoConverter}.
*
* @return
* @return never {@literal null}.
*/
MongoConverter getConverter();
}

View File

@@ -35,7 +35,6 @@ import org.bson.codecs.Codec;
import org.bson.conversions.Bson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -69,9 +68,7 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
import org.springframework.data.mongodb.core.aggregation.Fields;
import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
@@ -111,6 +108,7 @@ import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.data.mongodb.core.query.Meta.CursorOption;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter;
import org.springframework.data.mongodb.core.validation.Validator;
@@ -437,7 +435,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
@SuppressWarnings("ConstantConditions")
protected <T> CloseableIterator<T> doStream(Query query, Class<?> entityType, String collectionName,
protected <T> CloseableIterator<T> doStream(Query query, final Class<?> entityType, String collectionName,
Class<T> returnType) {
Assert.notNull(query, "Query must not be null!");
@@ -471,7 +469,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
*/
@Override
@SuppressWarnings("ConstantConditions")
public Document executeCommand(String jsonCommand) {
public Document executeCommand(final String jsonCommand) {
Assert.hasText(jsonCommand, "JsonCommand must not be null nor empty!");
@@ -484,7 +482,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
*/
@Override
@SuppressWarnings("ConstantConditions")
public Document executeCommand(Document command) {
public Document executeCommand(final Document command) {
Assert.notNull(command, "Command must not be null!");
@@ -655,7 +653,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.MongoOperations#createCollection(java.lang.String)
*/
public MongoCollection<Document> createCollection(String collectionName) {
public MongoCollection<Document> createCollection(final String collectionName) {
Assert.notNull(collectionName, "CollectionName must not be null!");
@@ -666,8 +664,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.MongoOperations#createCollection(java.lang.String, org.springframework.data.mongodb.core.CollectionOptions)
*/
public MongoCollection<Document> createCollection(String collectionName,
@Nullable CollectionOptions collectionOptions) {
public MongoCollection<Document> createCollection(final String collectionName,
final @Nullable CollectionOptions collectionOptions) {
Assert.notNull(collectionName, "CollectionName must not be null!");
return doCreateCollection(collectionName, convertToDocument(collectionOptions));
@@ -678,7 +676,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* @see org.springframework.data.mongodb.core.MongoOperations#getCollection(java.lang.String)
*/
@SuppressWarnings("ConstantConditions")
public MongoCollection<Document> getCollection(String collectionName) {
public MongoCollection<Document> getCollection(final String collectionName) {
Assert.notNull(collectionName, "CollectionName must not be null!");
@@ -698,7 +696,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* @see org.springframework.data.mongodb.core.ExecutableInsertOperation#getCollection(java.lang.String)
*/
@SuppressWarnings("ConstantConditions")
public boolean collectionExists(String collectionName) {
public boolean collectionExists(final String collectionName) {
Assert.notNull(collectionName, "CollectionName must not be null!");
@@ -729,13 +727,15 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Assert.notNull(collectionName, "CollectionName must not be null!");
execute(collectionName, (CollectionCallback<Void>) collection -> {
collection.drop();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Dropped collection [{}]",
collection.getNamespace() != null ? collection.getNamespace().getCollectionName() : collectionName);
execute(collectionName, new CollectionCallback<Void>() {
public Void doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
collection.drop();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Dropped collection [{}]",
collection.getNamespace() != null ? collection.getNamespace().getCollectionName() : collectionName);
}
return null;
}
return null;
});
}
@@ -1045,25 +1045,25 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@Nullable
@Override
public <T> T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass) {
public <T> T findAndModify(Query query, Update update, Class<T> entityClass) {
return findAndModify(query, update, new FindAndModifyOptions(), entityClass, getCollectionName(entityClass));
}
@Nullable
@Override
public <T> T findAndModify(Query query, UpdateDefinition update, Class<T> entityClass, String collectionName) {
public <T> T findAndModify(Query query, Update update, Class<T> entityClass, String collectionName) {
return findAndModify(query, update, new FindAndModifyOptions(), entityClass, collectionName);
}
@Nullable
@Override
public <T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass) {
public <T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass) {
return findAndModify(query, update, options, entityClass, getCollectionName(entityClass));
}
@Nullable
@Override
public <T> T findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass,
public <T> T findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName) {
Assert.notNull(query, "Query must not be null!");
@@ -1152,7 +1152,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
@Override
public long count(Query query, String collectionName) {
public long count(final Query query, String collectionName) {
return count(query, null, collectionName);
}
@@ -1191,8 +1191,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
LOGGER.debug("Executing count: {} in collection: {}", serializeToJsonSafely(filter), collectionName);
}
return execute(collectionName,
collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), options));
if (MongoDatabaseUtils.isTransactionActive(getMongoDbFactory())) {
return execute(collectionName, collection -> collection.countDocuments(filter, options));
}
return execute(collectionName, collection -> collection.count(filter, options));
}
/*
@@ -1233,7 +1236,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
/**
* Prepare the collection before any processing is done using it. This allows a convenient way to apply settings like
* slaveOk() etc. Can be overridden in sub-classes.
* withCodecRegistry() etc. Can be overridden in sub-classes.
*
* @param collection
*/
@@ -1482,7 +1485,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
@SuppressWarnings("ConstantConditions")
protected Object insertDocument(String collectionName, Document document, Class<?> entityClass) {
protected Object insertDocument(final String collectionName, final Document document, final Class<?> entityClass) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Inserting Document containing fields: {} in collection: {}", document.keySet(), collectionName);
@@ -1503,7 +1506,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
});
}
protected List<Object> insertDocumentList(String collectionName, List<Document> documents) {
protected List<Object> insertDocumentList(final String collectionName, final List<Document> documents) {
if (documents.isEmpty()) {
return Collections.emptyList();
@@ -1531,47 +1534,49 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return MappedDocument.toIds(documents);
}
protected Object saveDocument(String collectionName, Document dbDoc, Class<?> entityClass) {
protected Object saveDocument(final String collectionName, final Document dbDoc, final Class<?> entityClass) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Saving Document containing fields: {}", dbDoc.keySet());
}
return execute(collectionName, collection -> {
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass,
dbDoc, null);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
return execute(collectionName, new CollectionCallback<Object>() {
public Object doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.SAVE, collectionName, entityClass,
dbDoc, null);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
MappedDocument mapped = MappedDocument.of(dbDoc);
MappedDocument mapped = MappedDocument.of(dbDoc);
if (!mapped.hasId()) {
if (writeConcernToUse == null) {
collection.insertOne(dbDoc);
if (!mapped.hasId()) {
if (writeConcernToUse == null) {
collection.insertOne(dbDoc);
} else {
collection.withWriteConcern(writeConcernToUse).insertOne(dbDoc);
}
} else if (writeConcernToUse == null) {
collection.replaceOne(mapped.getIdFilter(), dbDoc, new ReplaceOptions().upsert(true));
} else {
collection.withWriteConcern(writeConcernToUse).insertOne(dbDoc);
collection.withWriteConcern(writeConcernToUse).replaceOne(mapped.getIdFilter(), dbDoc,
new ReplaceOptions().upsert(true));
}
} else if (writeConcernToUse == null) {
collection.replaceOne(mapped.getIdFilter(), dbDoc, new ReplaceOptions().upsert(true));
} else {
collection.withWriteConcern(writeConcernToUse).replaceOne(mapped.getIdFilter(), dbDoc,
new ReplaceOptions().upsert(true));
return mapped.getId();
}
return mapped.getId();
});
}
@Override
public UpdateResult upsert(Query query, UpdateDefinition update, Class<?> entityClass) {
public UpdateResult upsert(Query query, Update update, Class<?> entityClass) {
return doUpdate(getCollectionName(entityClass), query, update, entityClass, true, false);
}
@Override
public UpdateResult upsert(Query query, UpdateDefinition update, String collectionName) {
public UpdateResult upsert(Query query, Update update, String collectionName) {
return doUpdate(collectionName, query, update, null, true, false);
}
@Override
public UpdateResult upsert(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName) {
public UpdateResult upsert(Query query, Update update, Class<?> entityClass, String collectionName) {
Assert.notNull(entityClass, "EntityClass must not be null!");
@@ -1579,17 +1584,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
@Override
public UpdateResult updateFirst(Query query, UpdateDefinition update, Class<?> entityClass) {
public UpdateResult updateFirst(Query query, Update update, Class<?> entityClass) {
return doUpdate(getCollectionName(entityClass), query, update, entityClass, false, false);
}
@Override
public UpdateResult updateFirst(Query query, UpdateDefinition update, String collectionName) {
public UpdateResult updateFirst(final Query query, final Update update, final String collectionName) {
return doUpdate(collectionName, query, update, null, false, false);
}
@Override
public UpdateResult updateFirst(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName) {
public UpdateResult updateFirst(Query query, Update update, Class<?> entityClass, String collectionName) {
Assert.notNull(entityClass, "EntityClass must not be null!");
@@ -1597,17 +1602,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
@Override
public UpdateResult updateMulti(Query query, UpdateDefinition update, Class<?> entityClass) {
public UpdateResult updateMulti(Query query, Update update, Class<?> entityClass) {
return doUpdate(getCollectionName(entityClass), query, update, entityClass, false, true);
}
@Override
public UpdateResult updateMulti(Query query, UpdateDefinition update, String collectionName) {
public UpdateResult updateMulti(final Query query, final Update update, String collectionName) {
return doUpdate(collectionName, query, update, null, false, true);
}
@Override
public UpdateResult updateMulti(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName) {
public UpdateResult updateMulti(final Query query, final Update update, Class<?> entityClass, String collectionName) {
Assert.notNull(entityClass, "EntityClass must not be null!");
@@ -1615,8 +1620,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
@SuppressWarnings("ConstantConditions")
protected UpdateResult doUpdate(String collectionName, Query query, UpdateDefinition update,
@Nullable Class<?> entityClass, boolean upsert, boolean multi) {
protected UpdateResult doUpdate(final String collectionName, final Query query, final UpdateDefinition update,
@Nullable final Class<?> entityClass, final boolean upsert, final boolean multi) {
Assert.notNull(collectionName, "CollectionName must not be null!");
Assert.notNull(query, "Query must not be null!");
@@ -1628,54 +1633,25 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
upsert ? "Upsert" : "UpdateFirst", serializeToJsonSafely(query.getSortObject()));
}
MongoPersistentEntity<?> entity = entityClass == null ? null : getPersistentEntity(entityClass);
increaseVersionForUpdateIfNecessary(entity, update);
UpdateOptions opts = new UpdateOptions();
opts.upsert(upsert);
if (update.hasArrayFilters()) {
opts.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList()));
}
Document queryObj = new Document();
if (query != null) {
queryObj.putAll(queryMapper.getMappedObject(query.getQueryObject(), entity));
}
if (multi && update.isIsolated() && !queryObj.containsKey("$isolated")) {
queryObj.put("$isolated", 1);
}
if (update instanceof AggregationUpdate) {
AggregationOperationContext context = entityClass != null
? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper)
: Aggregation.DEFAULT_CONTEXT;
List<Document> pipeline = new AggregationUtil(queryMapper, mappingContext)
.createPipeline((AggregationUpdate) update, context);
return execute(collectionName, collection -> {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Calling update using query: {} and update: {} in collection: {}",
serializeToJsonSafely(queryObj), serializeToJsonSafely(pipeline), collectionName);
}
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName,
entityClass, update.getUpdateObject(), queryObj);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection;
return multi ? collection.updateMany(queryObj, pipeline, opts) : collection.updateOne(queryObj, pipeline, opts);
});
}
return execute(collectionName, collection -> {
MongoPersistentEntity<?> entity = entityClass == null ? null : getPersistentEntity(entityClass);
increaseVersionForUpdateIfNecessary(entity, update);
UpdateOptions opts = new UpdateOptions();
opts.upsert(upsert);
if (update.hasArrayFilters()) {
opts.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument).collect(Collectors.toList()));
}
Document queryObj = new Document();
if (query != null) {
queryObj.putAll(queryMapper.getMappedObject(query.getQueryObject(), entity));
}
operations.forType(entityClass) //
.getCollation(query) //
.map(Collation::toMongoCollation) //
@@ -1684,6 +1660,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Document updateObj = update instanceof MappedUpdate ? update.getUpdateObject()
: updateMapper.getMappedObject(update.getUpdateObject(), entity);
if (multi && update.isIsolated() && !queryObj.containsKey("$isolated")) {
queryObj.put("$isolated", 1);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Calling update using query: {} and update: {} in collection: {}", serializeToJsonSafely(queryObj),
serializeToJsonSafely(updateObj), collectionName);
@@ -1703,8 +1683,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return collection.replaceOne(queryObj, updateObj, replaceOptions);
} else {
return multi ? collection.updateMany(queryObj, updateObj, opts)
: collection.updateOne(queryObj, updateObj, opts);
if (multi) {
return collection.updateMany(queryObj, updateObj, opts);
} else {
return collection.updateOne(queryObj, updateObj, opts);
}
}
});
}
@@ -1757,14 +1740,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
@SuppressWarnings("ConstantConditions")
protected <T> DeleteResult doRemove(String collectionName, Query query, @Nullable Class<T> entityClass,
boolean multi) {
protected <T> DeleteResult doRemove(final String collectionName, final Query query,
@Nullable final Class<T> entityClass, boolean multi) {
Assert.notNull(query, "Query must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
Document queryObject = queryMapper.getMappedObject(query.getQueryObject(), entity);
final MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
final Document queryObject = queryMapper.getMappedObject(query.getQueryObject(), entity);
return execute(collectionName, collection -> {
@@ -2162,7 +2145,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
protected <O> AggregationResults<O> doAggregate(Aggregation aggregation, String collectionName, Class<O> outputType,
AggregationOperationContext context) {
ReadDocumentCallback<O> callback = new ReadDocumentCallback<>(mongoConverter, outputType, collectionName);
DocumentCallback<O> callback = new UnwrapAndReadDocumentCallback<>(mongoConverter, outputType, collectionName);
AggregationOptions options = aggregation.getOptions();
AggregationUtil aggregationUtil = new AggregationUtil(queryMapper, mappingContext);
@@ -2207,10 +2190,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
options.getComment().ifPresent(aggregateIterable::comment);
if (options.hasExecutionTimeLimit()) {
aggregateIterable = aggregateIterable.maxTime(options.getMaxTime().toMillis(), TimeUnit.MILLISECONDS);
}
MongoIterable<O> iterable = aggregateIterable.map(val -> {
rawResult.add(val);
@@ -2672,7 +2651,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@SuppressWarnings("ConstantConditions")
protected <T> T doFindAndModify(String collectionName, Document query, Document fields, Document sort,
Class<T> entityClass, UpdateDefinition update, @Nullable FindAndModifyOptions options) {
Class<T> entityClass, Update update, @Nullable FindAndModifyOptions options) {
EntityReader<? super T, Bson> readerToUse = this.mongoConverter;
@@ -2685,18 +2664,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
increaseVersionForUpdateIfNecessary(entity, update);
Document mappedQuery = queryMapper.getMappedObject(query, entity);
Object mappedUpdate;
if (update instanceof AggregationUpdate) {
AggregationOperationContext context = entityClass != null
? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper)
: Aggregation.DEFAULT_CONTEXT;
mappedUpdate = new AggregationUtil(queryMapper, mappingContext).createPipeline((Aggregation) update, context);
} else {
mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity);
}
Document mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
@@ -3070,11 +3038,11 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
private final Document query;
private final Document fields;
private final Document sort;
private final Object update;
private final Document update;
private final List<Document> arrayFilters;
private final FindAndModifyOptions options;
public FindAndModifyCallback(Document query, Document fields, Document sort, Object update,
public FindAndModifyCallback(Document query, Document fields, Document sort, Document update,
List<Document> arrayFilters, FindAndModifyOptions options) {
this.query = query;
this.fields = fields;
@@ -3102,13 +3070,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
opts.arrayFilters(arrayFilters);
}
if (update instanceof Document) {
return collection.findOneAndUpdate(query, (Document) update, opts);
} else if (update instanceof List) {
return collection.findOneAndUpdate(query, (List<Document>) update, opts);
}
throw new IllegalArgumentException(String.format("Using %s is not supported in findOneAndUpdate", update));
return collection.findOneAndUpdate(query, update, opts);
}
}
@@ -3193,12 +3155,13 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@Nullable
public T doWith(@Nullable Document object) {
T source = null;
if (null != object) {
maybeEmitEvent(new AfterLoadEvent<>(object, type, collectionName));
source = reader.read(type, object);
}
T source = reader.read(type, object);
if (null != source) {
maybeEmitEvent(new AfterConvertEvent<>(object, source, collectionName));
}
@@ -3238,9 +3201,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Class<?> typeToRead = targetType.isInterface() || targetType.isAssignableFrom(entityType) ? entityType
: targetType;
if (null != object) {
maybeEmitEvent(new AfterLoadEvent<>(object, targetType, collectionName));
}
maybeEmitEvent(new AfterLoadEvent<>(object, targetType, collectionName));
Object source = reader.read(typeToRead, object);
Object result = targetType.isInterface() ? projectionFactory.createProjection(targetType, source) : source;
@@ -3253,6 +3214,39 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
}
class UnwrapAndReadDocumentCallback<T> extends ReadDocumentCallback<T> {
public UnwrapAndReadDocumentCallback(EntityReader<? super T, Bson> reader, Class<T> type, String collectionName) {
super(reader, type, collectionName);
}
@Override
public T doWith(@Nullable Document object) {
if (object == null) {
return null;
}
Object idField = object.get(Fields.UNDERSCORE_ID);
if (!(idField instanceof Document)) {
return super.doWith(object);
}
Document toMap = new Document();
Document nested = (Document) idField;
toMap.putAll(nested);
for (String key : object.keySet()) {
if (!Fields.UNDERSCORE_ID.equals(key)) {
toMap.put(key, object.get(key));
}
}
return super.doWith(toMap);
}
}
class QueryCursorPreparer implements CursorPreparer {
private final Query query;
@@ -3268,9 +3262,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.CursorPreparer#prepare(com.mongodb.DBCursor)
*/
public FindIterable<Document> prepare(FindIterable<Document> cursor) {
public FindIterable<Document> prepare(FindIterable<Document> iterable) {
FindIterable<Document> cursorToUse = cursor;
FindIterable<Document> cursorToUse = iterable;
operations.forType(type).getCollation(query) //
.map(Collation::toMongoCollation) //
@@ -3330,6 +3324,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
case PARTIAL:
cursorToUse = cursorToUse.partial(true);
break;
case SECONDARY_READS:
case SLAVE_OK:
break;
default:
@@ -3347,7 +3342,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
@Override
public ReadPreference getReadPreference() {
return query.getMeta().getFlags().contains(CursorOption.SLAVE_OK) ? ReadPreference.primaryPreferred() : null;
return (query.getMeta().getFlags().contains(CursorOption.SECONDARY_READS)
|| query.getMeta().getFlags().contains(CursorOption.SLAVE_OK)) ? ReadPreference.primaryPreferred() : null;
}
}
@@ -3528,5 +3524,19 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
// native MongoDB objects that offer methods with ClientSession must not be proxied.
return delegate.getDb();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.MongoTemplate#doCount(java.lang.String, org.bson.Document, com.mongodb.client.model.CountOptions)
*/
@Override
protected long doCount(String collectionName, Document filter, CountOptions options) {
if (!session.hasActiveTransaction()) {
return super.doCount(collectionName, filter, options);
}
return execute(collectionName, collection -> collection.countDocuments(filter, options));
}
}
}

View File

@@ -29,7 +29,6 @@ import org.springframework.data.geo.GeoResult;
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;
@@ -40,7 +39,6 @@ import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.lang.Nullable;
import org.springframework.transaction.reactive.TransactionalOperator;
import org.springframework.util.Assert;
@@ -680,14 +678,11 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
* @return the converted object that was updated before it was updated.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
<T> Mono<T> findAndModify(Query query, UpdateDefinition update, Class<T> entityClass);
<T> Mono<T> findAndModify(Query query, Update update, Class<T> entityClass);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
@@ -695,15 +690,12 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
* @param collectionName the collection to query. Must not be {@literal null}.
* @return the converted object that was updated before it was updated.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
<T> Mono<T> findAndModify(Query query, UpdateDefinition update, Class<T> entityClass, String collectionName);
<T> Mono<T> findAndModify(Query query, Update update, Class<T> entityClass, String collectionName);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
@@ -712,16 +704,13 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification.
* @param update the {@link UpdateDefinition} to apply on matching documents.
* @param update the {@link Update} to apply on matching documents.
* @param options the {@link FindAndModifyOptions} holding additional information.
* @param entityClass the parametrized type.
* @return the converted object that was updated. Depending on the value of {@link FindAndModifyOptions#isReturnNew()}
* this will either be the object as it was before the update or as it is after the update.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
<T> Mono<T> findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass);
<T> Mono<T> findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass);
/**
* Triggers <a href="https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/">findAndModify<a/>
@@ -730,17 +719,14 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
*
* @param query the {@link Query} class that specifies the {@link Criteria} used to find a record and also an optional
* fields specification. Must not be {@literal null}.
* @param update the {@link UpdateDefinition} to apply on matching documents. Must not be {@literal null}.
* @param update the {@link Update} to apply on matching documents. Must not be {@literal null}.
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
* @param entityClass the parametrized type. Must not be {@literal null}.
* @param collectionName the collection to query. Must not be {@literal null}.
* @return the converted object that was updated. Depending on the value of {@link FindAndModifyOptions#isReturnNew()}
* this will either be the object as it was before the update or as it is after the update.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
<T> Mono<T> findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options, Class<T> entityClass,
<T> Mono<T> findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName);
/**
@@ -1163,111 +1149,99 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document. <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, UpdateDefinition, Class)} instead.
* Use {@link #findAndModify(Query, Update, Class)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be upserted. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing object. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object. Must not be {@literal null}.
* @param entityClass class that determines the collection to use. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> upsert(Query query, UpdateDefinition update, Class<?> entityClass);
Mono<UpdateResult> upsert(Query query, Update update, Class<?> entityClass);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #upsert(Query, UpdateDefinition, Class, String)} to get full type specific
* support.
* domain type information. Use {@link #upsert(Query, Update, Class, String)} to get full type specific support.
* <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, Update, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be upserted. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing object. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> upsert(Query query, UpdateDefinition update, String collectionName);
Mono<UpdateResult> upsert(Query query, Update update, String collectionName);
/**
* Performs an upsert. If no document is found that matches the query, a new document is created and inserted by
* combining the query document and the update document.
* combining the query document and the update document. <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, Update, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be upserted. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing object. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing
* object. Must not be {@literal null}.
* @param entityClass class of the pojo to be operated on. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> upsert(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName);
Mono<UpdateResult> upsert(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Updates the first object that is found in the collection of the entity class that matches the query document with
* the provided update document. <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, UpdateDefinition, Class)} instead.
* Use {@link #findAndModify(Query, Update, Class)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param entityClass class that determines the collection to use.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> updateFirst(Query query, UpdateDefinition update, Class<?> entityClass);
Mono<UpdateResult> updateFirst(Query query, Update update, Class<?> entityClass);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #updateFirst(Query, UpdateDefinition, Class, String)} to get full type specific
* support. <br />
* domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support.
* <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, UpdateDefinition, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
*/
Mono<UpdateResult> updateFirst(Query query, Update update, String collectionName);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document. <br />
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
* Use {@link #findAndModify(Query, Update, Class, String)} instead.
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> updateFirst(Query query, UpdateDefinition update, String collectionName);
/**
* Updates the first object that is found in the specified collection that matches the query document criteria with
* the provided updated document. <br />
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param entityClass class of the pojo to be operated on. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> updateFirst(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName);
Mono<UpdateResult> updateFirst(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
@@ -1275,34 +1249,27 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param entityClass class of the pojo to be operated on. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> updateMulti(Query query, UpdateDefinition update, Class<?> entityClass);
Mono<UpdateResult> updateMulti(Query query, Update update, Class<?> entityClass);
/**
* Updates all objects that are found in the specified collection that matches the query document criteria with the
* provided updated document. <br />
* <strong>NOTE:</strong> Any additional support for field mapping, versions, etc. is not available due to the lack of
* domain type information. Use {@link #updateMulti(Query, UpdateDefinition, Class, String)} to get full type specific
* support.
* domain type information. Use {@link #updateMulti(Query, Update, Class, String)} to get full type specific support.
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> updateMulti(Query query, UpdateDefinition update, String collectionName);
Mono<UpdateResult> updateMulti(Query query, Update update, String collectionName);
/**
* Updates all objects that are found in the collection for the entity class that matches the query document criteria
@@ -1310,16 +1277,13 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
*
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
* {@literal null}.
* @param update the {@link UpdateDefinition} that contains the updated object or {@code $} operators to manipulate
* the existing. Must not be {@literal null}.
* @param update the update document that contains the updated object or $ operators to manipulate the existing. Must
* not be {@literal null}.
* @param entityClass class of the pojo to be operated on. Must not be {@literal null}.
* @param collectionName name of the collection to update the object in. Must not be {@literal null}.
* @return the {@link UpdateResult} which lets you access the results of the previous write.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
Mono<UpdateResult> updateMulti(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName);
Mono<UpdateResult> updateMulti(Query query, Update update, Class<?> entityClass, String collectionName);
/**
* Remove the given object from the collection by id.
@@ -1571,7 +1535,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
/**
* Returns the underlying {@link MongoConverter}.
*
* @return
* @return never {@literal null}.
*/
MongoConverter getConverter();
@@ -1579,7 +1543,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
* The collection name used for the specified class by this template.
*
* @param entityClass must not be {@literal null}.
* @return
* @return never {@literal null}.
* @since 2.1
*/
String getCollectionName(Class<?> entityClass);

View File

@@ -40,6 +40,7 @@ import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -69,9 +70,7 @@ import org.springframework.data.mongodb.core.EntityOperations.AdaptibleEntity;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.AggregationOptions;
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
import org.springframework.data.mongodb.core.aggregation.PrefixingDelegatingAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.RelaxedTypeBasedAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
@@ -107,6 +106,7 @@ import org.springframework.data.mongodb.core.query.Meta;
import org.springframework.data.mongodb.core.query.Meta.CursorOption;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter;
import org.springframework.data.mongodb.core.validation.Validator;
@@ -123,9 +123,6 @@ import org.springframework.util.StringUtils;
import com.mongodb.ClientSessionOptions;
import com.mongodb.CursorType;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern;
@@ -323,8 +320,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
/**
* Configures the {@link WriteConcern} to be used with the template. If none is configured the {@link WriteConcern}
* configured on the {@link MongoDbFactory} will apply. If you configured a {@link Mongo} instance no
* {@link WriteConcern} will be used.
* configured on the {@link MongoDbFactory} will apply.
*
* @param writeConcern can be {@literal null}.
*/
@@ -1074,10 +1070,6 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
.map(Collation::toMongoCollation) //
.ifPresent(cursor::collation);
if (options.hasExecutionTimeLimit()) {
cursor = cursor.maxTime(options.getMaxTime().toMillis(), TimeUnit.MILLISECONDS);
}
return Flux.from(cursor).map(readCallback::doWith);
}
@@ -1126,38 +1118,36 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findAndModify(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.Class)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findAndModify(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.Class)
*/
public <T> Mono<T> findAndModify(Query query, UpdateDefinition update, Class<T> entityClass) {
public <T> Mono<T> findAndModify(Query query, Update update, Class<T> entityClass) {
return findAndModify(query, update, new FindAndModifyOptions(), entityClass, getCollectionName(entityClass));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findAndModify(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.Class, java.lang.String)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findAndModify(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.Class, java.lang.String)
*/
public <T> Mono<T> findAndModify(Query query, UpdateDefinition update, Class<T> entityClass, String collectionName) {
public <T> Mono<T> findAndModify(Query query, Update update, Class<T> entityClass, String collectionName) {
return findAndModify(query, update, new FindAndModifyOptions(), entityClass, collectionName);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findAndModify(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, org.springframework.data.mongodb.core.FindAndModifyOptions, java.lang.Class)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findAndModify(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, org.springframework.data.mongodb.core.FindAndModifyOptions, java.lang.Class)
*/
public <T> Mono<T> findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
Class<T> entityClass) {
public <T> Mono<T> findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass) {
return findAndModify(query, update, options, entityClass, getCollectionName(entityClass));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findAndModify(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, org.springframework.data.mongodb.core.FindAndModifyOptions, java.lang.Class, java.lang.String)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findAndModify(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, org.springframework.data.mongodb.core.FindAndModifyOptions, java.lang.Class, java.lang.String)
*/
public <T> Mono<T> findAndModify(Query query, UpdateDefinition update, FindAndModifyOptions options,
Class<T> entityClass, String collectionName) {
public <T> Mono<T> findAndModify(Query query, Update update, FindAndModifyOptions options, Class<T> entityClass,
String collectionName) {
Assert.notNull(options, "Options must not be null! ");
Assert.notNull(entityClass, "Entity class must not be null!");
FindAndModifyOptions optionsToUse = FindAndModifyOptions.of(options);
@@ -1168,6 +1158,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
if (!optionsToUse.getCollation().isPresent()) {
operations.forType(entityClass).getCollation(query).ifPresent(optionsToUse::collation);
;
}
return doFindAndModify(collectionName, query.getQueryObject(), query.getFieldsObject(),
@@ -1306,8 +1297,9 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
*/
protected Mono<Long> doCount(String collectionName, Document filter, CountOptions options) {
return createMono(collectionName,
collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), options));
return ReactiveMongoDatabaseUtils.isTransactionActive(mongoDatabaseFactory) //
.flatMap(txActive -> createMono(collectionName,
collection -> txActive ? collection.countDocuments(filter, options) : collection.count(filter, options)));
}
/*
@@ -1689,75 +1681,73 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#upsert(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.Class)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#upsert(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.Class)
*/
public Mono<UpdateResult> upsert(Query query, UpdateDefinition update, Class<?> entityClass) {
public Mono<UpdateResult> upsert(Query query, Update update, Class<?> entityClass) {
return doUpdate(getCollectionName(entityClass), query, update, entityClass, true, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#upsert(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.String)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#upsert(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.String)
*/
public Mono<UpdateResult> upsert(Query query, UpdateDefinition update, String collectionName) {
public Mono<UpdateResult> upsert(Query query, Update update, String collectionName) {
return doUpdate(collectionName, query, update, null, true, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#upsert(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.Class, java.lang.String)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#upsert(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.Class, java.lang.String)
*/
public Mono<UpdateResult> upsert(Query query, UpdateDefinition update, Class<?> entityClass, String collectionName) {
public Mono<UpdateResult> upsert(Query query, Update update, Class<?> entityClass, String collectionName) {
return doUpdate(collectionName, query, update, entityClass, true, false);
}
/*
* (non-Javadoc))
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateFirst(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.Class)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateFirst(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.Class)
*/
public Mono<UpdateResult> updateFirst(Query query, UpdateDefinition update, Class<?> entityClass) {
public Mono<UpdateResult> updateFirst(Query query, Update update, Class<?> entityClass) {
return doUpdate(getCollectionName(entityClass), query, update, entityClass, false, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateFirst(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.String)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateFirst(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.String)
*/
public Mono<UpdateResult> updateFirst(Query query, UpdateDefinition update, String collectionName) {
public Mono<UpdateResult> updateFirst(Query query, Update update, String collectionName) {
return doUpdate(collectionName, query, update, null, false, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateFirst(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.Class, java.lang.String)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateFirst(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.Class, java.lang.String)
*/
public Mono<UpdateResult> updateFirst(Query query, UpdateDefinition update, Class<?> entityClass,
String collectionName) {
public Mono<UpdateResult> updateFirst(Query query, Update update, Class<?> entityClass, String collectionName) {
return doUpdate(collectionName, query, update, entityClass, false, false);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.Class)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.Class)
*/
public Mono<UpdateResult> updateMulti(Query query, UpdateDefinition update, Class<?> entityClass) {
public Mono<UpdateResult> updateMulti(Query query, Update update, Class<?> entityClass) {
return doUpdate(getCollectionName(entityClass), query, update, entityClass, false, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.String)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.String)
*/
public Mono<UpdateResult> updateMulti(Query query, UpdateDefinition update, String collectionName) {
public Mono<UpdateResult> updateMulti(Query query, Update update, String collectionName) {
return doUpdate(collectionName, query, update, null, false, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.UpdateDefinition, java.lang.Class, java.lang.String)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.Class, java.lang.String)
*/
public Mono<UpdateResult> updateMulti(Query query, UpdateDefinition update, Class<?> entityClass,
String collectionName) {
public Mono<UpdateResult> updateMulti(Query query, Update update, Class<?> entityClass, String collectionName) {
return doUpdate(collectionName, query, update, entityClass, false, true);
}
@@ -1771,87 +1761,56 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
}
MongoPersistentEntity<?> entity = entityClass == null ? null : getPersistentEntity(entityClass);
increaseVersionForUpdateIfNecessary(entity, update);
Document queryObj = queryMapper.getMappedObject(query.getQueryObject(), entity);
Flux<UpdateResult> result = execute(collectionName, collection -> {
UpdateOptions updateOptions = new UpdateOptions().upsert(upsert);
operations.forType(entityClass).getCollation(query) //
.map(Collation::toMongoCollation) //
.ifPresent(updateOptions::collation);
increaseVersionForUpdateIfNecessary(entity, update);
if (update.hasArrayFilters()) {
updateOptions.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument)
.map(it -> queryMapper.getMappedObject(it, entity)).collect(Collectors.toList()));
}
Document queryObj = queryMapper.getMappedObject(query.getQueryObject(), entity);
Document updateObj = update == null ? new Document()
: updateMapper.getMappedObject(update.getUpdateObject(), entity);
if (multi && update.isIsolated() && !queryObj.containsKey("$isolated")) {
queryObj.put("$isolated", 1);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s",
serializeToJsonSafely(queryObj), serializeToJsonSafely(updateObj), collectionName));
}
Flux<UpdateResult> result;
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass,
updateObj, queryObj);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
MongoCollection<Document> collectionToUse = prepareCollection(collection, writeConcernToUse);
if (update instanceof AggregationUpdate) {
UpdateOptions updateOptions = new UpdateOptions().upsert(upsert);
operations.forType(entityClass).getCollation(query) //
.map(Collation::toMongoCollation) //
.ifPresent(updateOptions::collation);
AggregationOperationContext context = entityClass != null
? new RelaxedTypeBasedAggregationOperationContext(entityClass, mappingContext, queryMapper)
: Aggregation.DEFAULT_CONTEXT;
if (update.hasArrayFilters()) {
updateOptions.arrayFilters(update.getArrayFilters().stream().map(ArrayFilter::asDocument)
.map(it -> queryMapper.getMappedObject(it, entity)).collect(Collectors.toList()));
}
List<Document> pipeline = new AggregationUtil(queryMapper, mappingContext)
.createPipeline((AggregationUpdate) update, context);
if (!UpdateMapper.isUpdateObject(updateObj)) {
result = execute(collectionName, collection -> {
ReplaceOptions replaceOptions = new ReplaceOptions();
replaceOptions.upsert(updateOptions.isUpsert());
replaceOptions.collation(updateOptions.getCollation());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s",
serializeToJsonSafely(queryObj), serializeToJsonSafely(pipeline), collectionName));
}
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName,
entityClass, update.getUpdateObject(), queryObj);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection;
return multi ? collection.updateMany(queryObj, pipeline, updateOptions)
: collection.updateOne(queryObj, pipeline, updateOptions);
});
} else {
result = execute(collectionName, collection -> {
Document updateObj = updateMapper.getMappedObject(update.getUpdateObject(), entity);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s",
serializeToJsonSafely(queryObj), serializeToJsonSafely(updateObj), collectionName));
}
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName,
entityClass, updateObj, queryObj);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
MongoCollection<Document> collectionToUse = prepareCollection(collection, writeConcernToUse);
if (!UpdateMapper.isUpdateObject(updateObj)) {
ReplaceOptions replaceOptions = new ReplaceOptions();
replaceOptions.upsert(updateOptions.isUpsert());
replaceOptions.collation(updateOptions.getCollation());
return collectionToUse.replaceOne(queryObj, updateObj, replaceOptions);
}
return multi ? collectionToUse.updateMany(queryObj, updateObj, updateOptions)
: collectionToUse.updateOne(queryObj, updateObj, updateOptions);
});
}
result = result.doOnNext(updateResult -> {
return collectionToUse.replaceOne(queryObj, updateObj, replaceOptions);
}
if (multi) {
return collectionToUse.updateMany(queryObj, updateObj, updateOptions);
}
return collectionToUse.updateOne(queryObj, updateObj, updateOptions);
}).doOnNext(updateResult -> {
if (entity != null && entity.hasVersionProperty() && !multi) {
if (updateResult.wasAcknowledged() && updateResult.getMatchedCount() == 0) {
Document updateObj = updateMapper.getMappedObject(update.getUpdateObject(), entity);
Document queryObj = query == null ? new Document()
: queryMapper.getMappedObject(query.getQueryObject(), entity);
Document updateObj = update == null ? new Document()
: updateMapper.getMappedObject(update.getUpdateObject(), entity);
if (containsVersionProperty(queryObj, entity))
throw new OptimisticLockingFailureException("Optimistic lock exception on saving entity: "
+ updateObj.toString() + " to collection " + collectionName);
@@ -2085,7 +2044,8 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
if (query == null) {
LOGGER.debug(String.format("Tail for class: %s in collection: %s", entityClass, collectionName));
// TODO: clean up
LOGGER.debug(String.format("find for class: %s in collection: %s", entityClass, collectionName));
return executeFindMultiInternal(
collection -> new FindCallback(null).doInCollection(collection).cursorType(CursorType.TailableAwait),
@@ -2437,8 +2397,8 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
* @param query the query document that specifies the criteria used to find a record.
* @param fields the document that specifies the fields to be returned.
* @param entityClass the parameterized type of the returned list.
* @param preparer allows for customization of the {@link DBCursor} used when iterating over the result set, (apply
* limits, skips and so on).
* @param preparer allows for customization of the {@link com.mongodb.client.FindIterable} used when iterating over
* the result set, (apply limits, skips and so on).
* @return the {@link List} of converted objects.
*/
protected <T> Flux<T> doFind(String collectionName, Document query, Document fields, Class<T> entityClass,
@@ -2576,25 +2536,16 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
}
protected <T> Mono<T> doFindAndModify(String collectionName, Document query, Document fields, Document sort,
Class<T> entityClass, UpdateDefinition update, FindAndModifyOptions options) {
Class<T> entityClass, Update update, FindAndModifyOptions options) {
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
increaseVersionForUpdateIfNecessary(entity, update);
return Mono.defer(() -> {
increaseVersionForUpdateIfNecessary(entity, update);
Document mappedQuery = queryMapper.getMappedObject(query, entity);
Object mappedUpdate;
if (update instanceof AggregationUpdate) {
AggregationOperationContext context = new RelaxedTypeBasedAggregationOperationContext(entityClass,
mappingContext, queryMapper);
mappedUpdate = new AggregationUtil(queryMapper, mappingContext).createPipeline((Aggregation) update, context);
} else {
mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity);
}
Document mappedUpdate = updateMapper.getMappedObject(update.getUpdateObject(), entity);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format(
@@ -2699,7 +2650,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
/**
* Prepare the collection before any processing is done using it. This allows a convenient way to apply settings like
* slaveOk() etc. Can be overridden in sub-classes.
* withCodecRegistry() etc. Can be overridden in sub-classes.
*
* @param collection
*/
@@ -2858,7 +2809,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
/**
* Simple {@link ReactiveCollectionCallback} that takes a query {@link Document} plus an optional fields specification
* {@link Document} and executes that against the {@link DBCollection}.
* {@link Document} and executes that against the {@link MongoCollection}.
*
* @author Oliver Gierke
* @author Thomas Risberg
@@ -2971,7 +2922,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
private final Document query;
private final Document fields;
private final Document sort;
private final Object update;
private final Document update;
private final List<Document> arrayFilters;
private final FindAndModifyOptions options;
@@ -2990,14 +2941,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
FindOneAndUpdateOptions findOneAndUpdateOptions = convertToFindOneAndUpdateOptions(options, fields, sort,
arrayFilters);
if (update instanceof Document) {
return collection.findOneAndUpdate(query, (Document) update, findOneAndUpdateOptions);
} else if (update instanceof List) {
return collection.findOneAndUpdate(query, (List<Document>) update, findOneAndUpdateOptions);
}
return Flux
.error(new IllegalArgumentException(String.format("Using %s is not supported in findOneAndUpdate", update)));
return collection.findOneAndUpdate(query, update, findOneAndUpdateOptions);
}
private static FindOneAndUpdateOptions convertToFindOneAndUpdateOptions(FindAndModifyOptions options,
@@ -3308,7 +3252,8 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
@Override
public ReadPreference getReadPreference() {
return query.getMeta().getFlags().contains(CursorOption.SLAVE_OK) ? ReadPreference.primaryPreferred() : null;
return (query.getMeta().getFlags().contains(CursorOption.SECONDARY_READS)
|| query.getMeta().getFlags().contains(CursorOption.SLAVE_OK)) ? ReadPreference.primaryPreferred() : null;
}
}
@@ -3376,6 +3321,20 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
// native MongoDB objects that offer methods with ClientSession must not be proxied.
return delegate.getMongoDatabase();
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoTemplate#count(java.lang.String, org.bson.Document, com.mongodb.client.model.CountOptions)
*/
@Override
public Mono<Long> doCount(String collectionName, Document filter, CountOptions options) {
if (!session.hasActiveTransaction()) {
return super.doCount(collectionName, filter, options);
}
return createMono(collectionName, collection -> collection.countDocuments(filter, options));
}
}
@RequiredArgsConstructor

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.data.mongodb.core;
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import reactor.core.publisher.Mono;
import org.springframework.data.mongodb.core.query.Query;
@@ -120,16 +118,13 @@ public interface ReactiveUpdateOperation {
interface UpdateWithUpdate<T> {
/**
* Set the {@link UpdateDefinition} to be applied.
* Set the {@link org.springframework.data.mongodb.core.query.Update} to be applied.
*
* @param update must not be {@literal null}.
* @return new instance of {@link TerminatingUpdate}. Never {@literal null}.
* @throws IllegalArgumentException if update is {@literal null}.
* @since 3.0
* @see Update
* @see AggregationUpdate
*/
TerminatingUpdate<T> apply(UpdateDefinition update);
TerminatingUpdate<T> apply(org.springframework.data.mongodb.core.query.Update update);
/**
* Specify {@code replacement} object.

View File

@@ -63,7 +63,7 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
@NonNull ReactiveMongoTemplate template;
@NonNull Class<?> domainType;
Query query;
org.springframework.data.mongodb.core.query.UpdateDefinition update;
org.springframework.data.mongodb.core.query.Update update;
@Nullable String collection;
@Nullable FindAndModifyOptions findAndModifyOptions;
@Nullable FindAndReplaceOptions findAndReplaceOptions;
@@ -72,10 +72,10 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.UpdateWithUpdate#apply(org.springframework.data.mongodb.core.query.UpdateDefinition)
* @see org.springframework.data.mongodb.core.ReactiveUpdateOperation.UpdateWithUpdate#apply(org.springframework.data.mongodb.core.query.Update)
*/
@Override
public TerminatingUpdate<T> apply(org.springframework.data.mongodb.core.query.UpdateDefinition update) {
public TerminatingUpdate<T> apply(org.springframework.data.mongodb.core.query.Update update) {
Assert.notNull(update, "Update must not be null!");

View File

@@ -242,7 +242,7 @@ public class SimpleReactiveMongoDatabaseFactory implements DisposableBean, React
factory.addAdvice(new SessionAwareMethodInterceptor<>(session, target, ClientSession.class, MongoDatabase.class,
this::proxyDatabase, MongoCollection.class, this::proxyCollection));
return targetType.cast(factory.getProxy());
return targetType.cast(factory.getProxy(target.getClass().getClassLoader()));
}
}
}

View File

@@ -16,8 +16,8 @@
package org.springframework.data.mongodb.core;
/**
* Enum to represent how strict the check of {@link com.mongodb.WriteResult} shall be. It can either be skipped entirely
* (use {@link #NONE}) or cause an exception to be thrown {@link #EXCEPTION}.
* Enum to represent how strict the check of {@link com.mongodb.WriteConcernResult} shall be. It can either be skipped
* entirely (use {@link #NONE}) or cause an exception to be thrown {@link #EXCEPTION}.
*
* @author Thomas Risberg
* @author Oliver Gierke

View File

@@ -17,6 +17,7 @@ package org.springframework.data.mongodb.core.aggregation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@@ -100,14 +101,14 @@ abstract class AbstractAggregationExpression implements AggregationExpression {
return value;
}
protected List<Object> append(Object value) {
protected List<Object> append(Object value, Expand expandList) {
if (this.value instanceof List) {
List<Object> clone = new ArrayList<Object>((List) this.value);
if (value instanceof List) {
clone.addAll((List) value);
if (value instanceof Collection && Expand.EXPAND_VALUES.equals(expandList)) {
clone.addAll((Collection<?>) value);
} else {
clone.add(value);
}
@@ -117,6 +118,17 @@ abstract class AbstractAggregationExpression implements AggregationExpression {
return Arrays.asList(this.value, value);
}
/**
* Expand a nested list of values to single entries or keep the list.
*/
protected enum Expand {
EXPAND_VALUES, KEEP_SOURCE
}
protected List<Object> append(Object value) {
return append(value, Expand.EXPAND_VALUES);
}
@SuppressWarnings("unchecked")
protected java.util.Map<String, Object> append(String key, Object value) {

View File

@@ -34,7 +34,7 @@ public class AccumulatorOperators {
* Take the numeric value referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link AccumulatorOperatorFactory}.
*/
public static AccumulatorOperatorFactory valueOf(String fieldReference) {
return new AccumulatorOperatorFactory(fieldReference);
@@ -44,7 +44,7 @@ public class AccumulatorOperators {
* Take the numeric value referenced resulting from given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link AccumulatorOperatorFactory}.
*/
public static AccumulatorOperatorFactory valueOf(AggregationExpression expression) {
return new AccumulatorOperatorFactory(expression);
@@ -86,7 +86,7 @@ public class AccumulatorOperators {
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates and
* returns the sum.
*
* @return
* @return new instance of {@link Sum}.
*/
public Sum sum() {
return usesFieldRef() ? Sum.sumOf(fieldReference) : Sum.sumOf(expression);
@@ -96,7 +96,7 @@ public class AccumulatorOperators {
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the
* average value.
*
* @return
* @return new instance of {@link Avg}.
*/
public Avg avg() {
return usesFieldRef() ? Avg.avgOf(fieldReference) : Avg.avgOf(expression);
@@ -106,7 +106,7 @@ public class AccumulatorOperators {
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the
* maximum value.
*
* @return
* @return new instance of {@link Max}.
*/
public Max max() {
return usesFieldRef() ? Max.maxOf(fieldReference) : Max.maxOf(expression);
@@ -116,7 +116,7 @@ public class AccumulatorOperators {
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the
* minimum value.
*
* @return
* @return new instance of {@link Min}.
*/
public Min min() {
return usesFieldRef() ? Min.minOf(fieldReference) : Min.minOf(expression);
@@ -126,7 +126,7 @@ public class AccumulatorOperators {
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates the
* population standard deviation of the input values.
*
* @return
* @return new instance of {@link StdDevPop}.
*/
public StdDevPop stdDevPop() {
return usesFieldRef() ? StdDevPop.stdDevPopOf(fieldReference) : StdDevPop.stdDevPopOf(expression);
@@ -136,7 +136,7 @@ public class AccumulatorOperators {
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates the
* sample standard deviation of the input values.
*
* @return
* @return new instance of {@link StdDevSamp}.
*/
public StdDevSamp stdDevSamp() {
return usesFieldRef() ? StdDevSamp.stdDevSampOf(fieldReference) : StdDevSamp.stdDevSampOf(expression);
@@ -167,7 +167,7 @@ public class AccumulatorOperators {
* Creates new {@link Sum}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Sum}.
*/
public static Sum sumOf(String fieldReference) {
@@ -179,7 +179,7 @@ public class AccumulatorOperators {
* Creates new {@link Sum}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Sum}.
*/
public static Sum sumOf(AggregationExpression expression) {
@@ -192,7 +192,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Sum}.
*/
public Sum and(String fieldReference) {
@@ -205,7 +205,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Sum}.
*/
public Sum and(AggregationExpression expression) {
@@ -264,7 +264,7 @@ public class AccumulatorOperators {
* Creates new {@link Avg}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Avg}.
*/
public static Avg avgOf(String fieldReference) {
@@ -276,7 +276,7 @@ public class AccumulatorOperators {
* Creates new {@link Avg}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Avg}.
*/
public static Avg avgOf(AggregationExpression expression) {
@@ -289,7 +289,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Avg}.
*/
public Avg and(String fieldReference) {
@@ -302,7 +302,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Avg}.
*/
public Avg and(AggregationExpression expression) {
@@ -347,7 +347,7 @@ public class AccumulatorOperators {
* Creates new {@link Max}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Max}.
*/
public static Max maxOf(String fieldReference) {
@@ -359,7 +359,7 @@ public class AccumulatorOperators {
* Creates new {@link Max}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Max}.
*/
public static Max maxOf(AggregationExpression expression) {
@@ -372,7 +372,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Max}.
*/
public Max and(String fieldReference) {
@@ -385,7 +385,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Max}.
*/
public Max and(AggregationExpression expression) {
@@ -430,7 +430,7 @@ public class AccumulatorOperators {
* Creates new {@link Min}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Min}.
*/
public static Min minOf(String fieldReference) {
@@ -442,7 +442,7 @@ public class AccumulatorOperators {
* Creates new {@link Min}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Min}.
*/
public static Min minOf(AggregationExpression expression) {
@@ -455,7 +455,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Min}.
*/
public Min and(String fieldReference) {
@@ -468,7 +468,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Min}.
*/
public Min and(AggregationExpression expression) {
@@ -513,7 +513,7 @@ public class AccumulatorOperators {
* Creates new {@link StdDevPop}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StdDevPop}.
*/
public static StdDevPop stdDevPopOf(String fieldReference) {
@@ -525,7 +525,7 @@ public class AccumulatorOperators {
* Creates new {@link StdDevPop} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link StdDevPop}.
*/
public static StdDevPop stdDevPopOf(AggregationExpression expression) {
@@ -538,7 +538,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StdDevPop}.
*/
public StdDevPop and(String fieldReference) {
@@ -551,7 +551,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link StdDevPop}.
*/
public StdDevPop and(AggregationExpression expression) {
@@ -596,7 +596,7 @@ public class AccumulatorOperators {
* Creates new {@link StdDevSamp}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StdDevSamp}.
*/
public static StdDevSamp stdDevSampOf(String fieldReference) {
@@ -608,7 +608,7 @@ public class AccumulatorOperators {
* Creates new {@link StdDevSamp}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link StdDevSamp}.
*/
public static StdDevSamp stdDevSampOf(AggregationExpression expression) {
@@ -621,7 +621,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StdDevSamp}.
*/
public StdDevSamp and(String fieldReference) {
@@ -634,7 +634,7 @@ public class AccumulatorOperators {
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link StdDevSamp}.
*/
public StdDevSamp and(AggregationExpression expression) {

View File

@@ -115,23 +115,12 @@ public class Aggregation {
return new Aggregation(operations);
}
/**
* Creates a new {@link AggregationUpdate} from the given {@link AggregationOperation}s.
*
* @param operations can be {@literal empty} but must not be {@literal null}.
* @return new instance of {@link AggregationUpdate}.
* @since 3.0
*/
public static AggregationUpdate newUpdate(AggregationOperation... operations) {
return AggregationUpdate.from(Arrays.asList(operations));
}
/**
* Returns a copy of this {@link Aggregation} with the given {@link AggregationOptions} set. Note that options are
* supported in MongoDB version 2.6+.
*
* @param options must not be {@literal null}.
* @return
* @return new instance of {@link Aggregation}.
* @since 1.6
*/
public Aggregation withOptions(AggregationOptions options) {
@@ -192,12 +181,13 @@ public class Aggregation {
/**
* Creates a new {@link Aggregation} from the given {@link AggregationOperation}s.
*
* @param aggregationOperations must not be {@literal null}.
* @param aggregationOperations must not be {@literal null} or empty.
* @param options must not be {@literal null} or empty.
*/
protected Aggregation(List<AggregationOperation> aggregationOperations, AggregationOptions options) {
Assert.notNull(aggregationOperations, "AggregationOperations must not be null!");
Assert.isTrue(!aggregationOperations.isEmpty(), "At least one AggregationOperation has to be provided");
Assert.notNull(options, "AggregationOptions must not be null!");
// check $out is the last operation if it exists
@@ -238,7 +228,7 @@ public class Aggregation {
* Creates a new {@link ProjectionOperation} including the given fields.
*
* @param fields must not be {@literal null}.
* @return
* @return new instance of {@link ProjectionOperation}.
*/
public static ProjectionOperation project(String... fields) {
return project(fields(fields));
@@ -248,7 +238,7 @@ public class Aggregation {
* Creates a new {@link ProjectionOperation} including the given {@link Fields}.
*
* @param fields must not be {@literal null}.
* @return
* @return new instance of {@link ProjectionOperation}.
*/
public static ProjectionOperation project(Fields fields) {
return new ProjectionOperation(fields);
@@ -271,7 +261,7 @@ public class Aggregation {
* Factory method to create a new {@link UnwindOperation} for the field with the given name.
*
* @param field must not be {@literal null} or empty.
* @return
* @return new instance of {@link UnwindOperation}.
*/
public static UnwindOperation unwind(String field) {
return new UnwindOperation(field(field));
@@ -281,7 +271,7 @@ public class Aggregation {
* Factory method to create a new {@link ReplaceRootOperation} for the field with the given name.
*
* @param fieldName must not be {@literal null} or empty.
* @return
* @return new instance of {@link ReplaceRootOperation}.
* @since 1.10
*/
public static ReplaceRootOperation replaceRoot(String fieldName) {
@@ -293,7 +283,7 @@ public class Aggregation {
* {@link AggregationExpression}.
*
* @param aggregationExpression must not be {@literal null}.
* @return
* @return new instance of {@link ReplaceRootOperation}.
* @since 1.10
*/
public static ReplaceRootOperation replaceRoot(AggregationExpression aggregationExpression) {
@@ -359,7 +349,7 @@ public class Aggregation {
* Creates a new {@link GroupOperation} for the given fields.
*
* @param fields must not be {@literal null}.
* @return
* @return new instance of {@link GroupOperation}.
*/
public static GroupOperation group(String... fields) {
return group(fields(fields));
@@ -380,7 +370,7 @@ public class Aggregation {
* {@link GraphLookupOperation} given {@literal fromCollection}.
*
* @param fromCollection must not be {@literal null} or empty.
* @return
* @return new instance of {@link StartWithBuilder} for creating a {@link GraphLookupOperation}.
* @since 1.10
*/
public static StartWithBuilder graphLookup(String fromCollection) {
@@ -391,7 +381,7 @@ public class Aggregation {
* Factory method to create a new {@link SortOperation} for the given {@link Sort}.
*
* @param sort must not be {@literal null}.
* @return
* @return new instance of {@link SortOperation}.
*/
public static SortOperation sort(Sort sort) {
return new SortOperation(sort);
@@ -402,7 +392,7 @@ public class Aggregation {
*
* @param direction must not be {@literal null}.
* @param fields must not be {@literal null}.
* @return
* @return new instance of {@link SortOperation}.
*/
public static SortOperation sort(Direction direction, String... fields) {
return new SortOperation(Sort.by(direction, fields));
@@ -412,7 +402,7 @@ public class Aggregation {
* Creates a new {@link SortByCountOperation} given {@literal groupByField}.
*
* @param field must not be {@literal null} or empty.
* @return
* @return new instance of {@link SortByCountOperation}.
* @since 2.1
*/
public static SortByCountOperation sortByCount(String field) {
@@ -423,7 +413,7 @@ public class Aggregation {
* Creates a new {@link SortByCountOperation} given {@link AggregationExpression group and sort expression}.
*
* @param groupAndSortExpression must not be {@literal null}.
* @return
* @return new instance of {@link SortByCountOperation}.
* @since 2.1
*/
public static SortByCountOperation sortByCount(AggregationExpression groupAndSortExpression) {
@@ -434,9 +424,10 @@ public class Aggregation {
* Creates a new {@link SkipOperation} skipping the given number of elements.
*
* @param elementsToSkip must not be less than zero.
* @return
* @return new instance of {@link SkipOperation}.
* @deprecated prepare to get this one removed in favor of {@link #skip(long)}.
*/
@Deprecated
public static SkipOperation skip(int elementsToSkip) {
return new SkipOperation(elementsToSkip);
}
@@ -445,7 +436,7 @@ public class Aggregation {
* Creates a new {@link SkipOperation} skipping the given number of elements.
*
* @param elementsToSkip must not be less than zero.
* @return
* @return new instance of {@link SkipOperation}.
*/
public static SkipOperation skip(long elementsToSkip) {
return new SkipOperation(elementsToSkip);
@@ -455,7 +446,7 @@ public class Aggregation {
* Creates a new {@link LimitOperation} limiting the result to the given number of elements.
*
* @param maxElements must not be less than zero.
* @return
* @return new instance of {@link LimitOperation}.
*/
public static LimitOperation limit(long maxElements) {
return new LimitOperation(maxElements);
@@ -465,7 +456,7 @@ public class Aggregation {
* Creates a new {@link SampleOperation} to select the specified number of documents from its input randomly.
*
* @param sampleSize must not be less than zero.
* @return
* @return new instance of {@link SampleOperation}.
* @since 2.0
*/
public static SampleOperation sample(long sampleSize) {
@@ -476,7 +467,7 @@ public class Aggregation {
* Creates a new {@link MatchOperation} using the given {@link Criteria}.
*
* @param criteria must not be {@literal null}.
* @return
* @return new instance of {@link MatchOperation}.
*/
public static MatchOperation match(Criteria criteria) {
return new MatchOperation(criteria);
@@ -486,7 +477,7 @@ public class Aggregation {
* Creates a new {@link MatchOperation} using the given {@link CriteriaDefinition}.
*
* @param criteria must not be {@literal null}.
* @return
* @return new instance of {@link MatchOperation}.
* @since 1.10
*/
public static MatchOperation match(CriteriaDefinition criteria) {
@@ -501,7 +492,7 @@ public class Aggregation {
* collection in the current database if one does not already exist. The collection is not visible until the
* aggregation completes. If the aggregation fails, MongoDB does not create the collection. Must not be
* {@literal null}.
* @return
* @return new instance of {@link OutOperation}.
*/
public static OutOperation out(String outCollectionName) {
return new OutOperation(outCollectionName);
@@ -511,7 +502,7 @@ public class Aggregation {
* Creates a new {@link BucketOperation} given {@literal groupByField}.
*
* @param groupByField must not be {@literal null} or empty.
* @return
* @return new instance of {@link BucketOperation}.
* @since 1.10
*/
public static BucketOperation bucket(String groupByField) {
@@ -522,7 +513,7 @@ public class Aggregation {
* Creates a new {@link BucketOperation} given {@link AggregationExpression group-by expression}.
*
* @param groupByExpression must not be {@literal null}.
* @return
* @return new instance of {@link BucketOperation}.
* @since 1.10
*/
public static BucketOperation bucket(AggregationExpression groupByExpression) {
@@ -534,7 +525,7 @@ public class Aggregation {
*
* @param groupByField must not be {@literal null} or empty.
* @param buckets number of buckets, must be a positive integer.
* @return
* @return new instance of {@link BucketAutoOperation}.
* @since 1.10
*/
public static BucketAutoOperation bucketAuto(String groupByField, int buckets) {
@@ -546,7 +537,7 @@ public class Aggregation {
*
* @param groupByExpression must not be {@literal null}.
* @param buckets number of buckets, must be a positive integer.
* @return
* @return new instance of {@link BucketAutoOperation}.
* @since 1.10
*/
public static BucketAutoOperation bucketAuto(AggregationExpression groupByExpression, int buckets) {
@@ -556,7 +547,7 @@ public class Aggregation {
/**
* Creates a new {@link FacetOperation}.
*
* @return
* @return new instance of {@link FacetOperation}.
* @since 1.10
*/
public static FacetOperation facet() {
@@ -567,7 +558,7 @@ public class Aggregation {
* Creates a new {@link FacetOperationBuilder} given {@link Aggregation}.
*
* @param aggregationOperations the sub-pipeline, must not be {@literal null}.
* @return
* @return new instance of {@link FacetOperation}.
* @since 1.10
*/
public static FacetOperationBuilder facet(AggregationOperation... aggregationOperations) {
@@ -616,7 +607,7 @@ public class Aggregation {
* Creates a new {@link Fields} instance for the given field names.
*
* @param fields must not be {@literal null}.
* @return
* @return new instance of {@link Fields}.
* @see Fields#fields(String...)
*/
public static Fields fields(String... fields) {
@@ -628,7 +619,7 @@ public class Aggregation {
*
* @param name must not be {@literal null} or empty.
* @param target must not be {@literal null} or empty.
* @return
* @return new instance of {@link Fields}.
*/
public static Fields bind(String name, String target) {
return Fields.from(field(name, target));
@@ -650,7 +641,7 @@ public class Aggregation {
/**
* Returns a new {@link AggregationOptions.Builder}.
*
* @return
* @return new instance of {@link AggregationOptions.Builder}.
* @since 1.6
*/
public static AggregationOptions.Builder newAggregationOptions() {
@@ -712,7 +703,7 @@ public class Aggregation {
* otherwise.
*
* @param fieldRef may be {@literal null}.
* @return
* @return {@literal true} if the given field refers to a {@link SystemVariable}.
*/
public static boolean isReferingToSystemVariable(@Nullable String fieldRef) {

View File

@@ -31,8 +31,8 @@ public interface AggregationExpression {
* Turns the {@link AggregationExpression} into a {@link Document} within the given
* {@link AggregationOperationContext}.
*
* @param context
* @return
* @param context must not be {@literal null}.
* @return the MongoDB native ({@link Document}) form of the expression.
*/
Document toDocument(AggregationOperationContext context);
}

View File

@@ -53,7 +53,7 @@ interface AggregationExpressionTransformer
* @param currentNode must not be {@literal null}.
* @param parentNode may be {@literal null}.
* @param previousOperationObject may be {@literal null}.
* @param aggregationContext must not be {@literal null}.
* @param context must not be {@literal null}.
*/
public AggregationExpressionTransformationContext(T currentNode, @Nullable ExpressionNode parentNode,
@Nullable Document previousOperationObject, AggregationOperationContext context) {
@@ -67,7 +67,7 @@ interface AggregationExpressionTransformer
/**
* Returns the underlying {@link AggregationOperationContext}.
*
* @return
* @return never {@literal null}.
*/
public AggregationOperationContext getAggregationContext() {
return aggregationContext;
@@ -76,7 +76,7 @@ interface AggregationExpressionTransformer
/**
* Returns the {@link FieldReference} for the current {@link ExpressionNode}.
*
* @return
* @return never {@literal null}.
*/
public FieldReference getFieldReference() {
return aggregationContext.getReference(getCurrentNode().getName());

View File

@@ -41,7 +41,7 @@ public enum AggregationFunctionExpressions {
* Returns an {@link AggregationExpression} build from the current {@link Enum} name and the given parameters.
*
* @param parameters must not be {@literal null}
* @return
* @return new instance of {@link AggregationExpression}.
*/
public AggregationExpression of(Object... parameters) {

View File

@@ -58,20 +58,20 @@ public interface AggregationOperationContext {
Document getMappedObject(Document document, @Nullable Class<?> type);
/**
* Returns a {@link FieldReference} for the given field or {@literal null} if the context does not expose the given
* field.
* Returns a {@link FieldReference} for the given field.
*
* @param field must not be {@literal null}.
* @return
* @return the {@link FieldReference} for the given {@link Field}.
* @throws IllegalArgumentException if the context does not expose a field with the given name
*/
FieldReference getReference(Field field);
/**
* Returns the {@link FieldReference} for the field with the given name or {@literal null} if the context does not
* expose a field with the given name.
* Returns the {@link FieldReference} for the field with the given name.
*
* @param name must not be {@literal null} or empty.
* @return
* @return the {@link FieldReference} for the field with given {@literal name}.
* @throws IllegalArgumentException if the context does not expose a field with the given name
*/
FieldReference getReference(String name);

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import java.time.Duration;
import java.util.Optional;
import org.bson.Document;
@@ -46,14 +45,12 @@ public class AggregationOptions {
private static final String ALLOW_DISK_USE = "allowDiskUse";
private static final String COLLATION = "collation";
private static final String COMMENT = "comment";
private static final String MAX_TIME = "maxTimeMS";
private final boolean allowDiskUse;
private final boolean explain;
private final Optional<Document> cursor;
private final Optional<Collation> collation;
private final Optional<String> comment;
private Duration maxTime = Duration.ZERO;
/**
* Creates a new {@link AggregationOptions}.
@@ -132,11 +129,7 @@ public class AggregationOptions {
: null;
String comment = document.getString(COMMENT);
AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
if (document.containsKey(MAX_TIME)) {
options.maxTime = Duration.ofMillis(document.getLong(MAX_TIME));
}
return options;
return new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
}
/**
@@ -153,7 +146,7 @@ public class AggregationOptions {
* Enables writing to temporary files. When set to true, aggregation stages can write data to the _tmp subdirectory in
* the dbPath directory.
*
* @return
* @return {@literal true} if enabled.
*/
public boolean isAllowDiskUse() {
return allowDiskUse;
@@ -162,7 +155,7 @@ public class AggregationOptions {
/**
* Specifies to return the information on the processing of the pipeline.
*
* @return
* @return {@literal true} if enabled.
*/
public boolean isExplain() {
return explain;
@@ -187,7 +180,7 @@ public class AggregationOptions {
/**
* Specify a document that contains options that control the creation of the cursor object.
*
* @return
* @return never {@literal null}.
*/
public Optional<Document> getCursor() {
return cursor;
@@ -196,7 +189,7 @@ public class AggregationOptions {
/**
* Get collation settings for string comparison.
*
* @return
* @return never {@literal null}.
* @since 2.0
*/
public Optional<Collation> getCollation() {
@@ -206,21 +199,13 @@ public class AggregationOptions {
/**
* Get the comment for the aggregation.
*
* @return
* @return never {@literal null}.
* @since 2.2
*/
public Optional<String> getComment() {
return comment;
}
/**
* @return the time limit for processing. {@link Duration#ZERO} is used for the default unbounded behavior.
* @since 3.0
*/
public Duration getMaxTime() {
return maxTime;
}
/**
* Returns a new potentially adjusted copy for the given {@code aggregationCommandObject} with the configuration
* applied.
@@ -248,17 +233,13 @@ public class AggregationOptions {
collation.map(Collation::toDocument).ifPresent(val -> result.append(COLLATION, val));
}
if (hasExecutionTimeLimit() && !result.containsKey(MAX_TIME)) {
result.append(MAX_TIME, maxTime.toMillis());
}
return result;
}
/**
* Returns a {@link Document} representation of this {@link AggregationOptions}.
*
* @return
* @return never {@literal null}.
*/
public Document toDocument() {
@@ -270,21 +251,9 @@ public class AggregationOptions {
collation.ifPresent(val -> document.append(COLLATION, val.toDocument()));
comment.ifPresent(val -> document.append(COMMENT, val));
if (hasExecutionTimeLimit()) {
document.append(MAX_TIME, maxTime.toMillis());
}
return document;
}
/**
* @return
* @since 3.0
*/
public boolean hasExecutionTimeLimit() {
return !maxTime.isZero() && !maxTime.isNegative();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@@ -310,13 +279,12 @@ public class AggregationOptions {
private @Nullable Document cursor;
private @Nullable Collation collation;
private @Nullable String comment;
private @Nullable Duration maxTime;
/**
* Defines whether to off-load intensive sort-operations to disk.
*
* @param allowDiskUse
* @return
* @param allowDiskUse use {@literal true} to allow disk use during the aggregation.
* @return this.
*/
public Builder allowDiskUse(boolean allowDiskUse) {
@@ -327,8 +295,8 @@ public class AggregationOptions {
/**
* Defines whether to get the execution plan for the aggregation instead of the actual results.
*
* @param explain
* @return
* @param explain use {@literal true} to enable explain feature.
* @return this.
*/
public Builder explain(boolean explain) {
@@ -339,8 +307,8 @@ public class AggregationOptions {
/**
* Additional options to the aggregation.
*
* @param cursor
* @return
* @param cursor must not be {@literal null}.
* @return this.
*/
public Builder cursor(Document cursor) {
@@ -351,8 +319,8 @@ public class AggregationOptions {
/**
* Define the initial cursor batch size.
*
* @param batchSize
* @return
* @param batchSize use a positive int.
* @return this.
* @since 2.0
*/
public Builder cursorBatchSize(int batchSize) {
@@ -365,7 +333,7 @@ public class AggregationOptions {
* Define collation settings for string comparison.
*
* @param collation can be {@literal null}.
* @return
* @return this.
* @since 2.0
*/
public Builder collation(@Nullable Collation collation) {
@@ -378,7 +346,7 @@ public class AggregationOptions {
* Define a comment to describe the execution.
*
* @param comment can be {@literal null}.
* @return
* @return this.
* @since 2.2
*/
public Builder comment(@Nullable String comment) {
@@ -387,33 +355,13 @@ public class AggregationOptions {
return this;
}
/**
* Set the time limit for processing.
*
* @param maxTime {@link Duration#ZERO} is used for the default unbounded behavior. {@link Duration#isNegative()
* Negative} values will be ignored.
* @return this.
* @since 3.0
*/
public Builder maxTime(@Nullable Duration maxTime) {
this.maxTime = maxTime;
return this;
}
/**
* Returns a new {@link AggregationOptions} instance with the given configuration.
*
* @return
* @return new instance of {@link AggregationOptions}.
*/
public AggregationOptions build() {
AggregationOptions options = new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
if (maxTime != null) {
options.maxTime = maxTime;
}
return options;
return new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
}
}
}

View File

@@ -59,7 +59,7 @@ public class AggregationResults<T> implements Iterable<T> {
/**
* Returns the aggregation results.
*
* @return
* @return the list of already mapped results or an empty one if none found.
*/
public List<T> getMappedResults() {
return mappedResults;
@@ -68,7 +68,7 @@ public class AggregationResults<T> implements Iterable<T> {
/**
* Returns the unique mapped result. Assumes no result or exactly one.
*
* @return
* @return the single already mapped result object or raise an error if more than one found.
* @throws IllegalArgumentException in case more than one result is available.
*/
@Nullable
@@ -88,7 +88,7 @@ public class AggregationResults<T> implements Iterable<T> {
/**
* Returns the server that has been used to perform the aggregation.
*
* @return
* @return can be {@literal null}.
*/
@Nullable
public String getServerUsed() {
@@ -98,7 +98,7 @@ public class AggregationResults<T> implements Iterable<T> {
/**
* Returns the raw result that was returned by the server.
*
* @return
* @return the raw response.
* @since 1.6
*/
public Document getRawResults() {

View File

@@ -56,7 +56,7 @@ public class AggregationSpELExpression implements AggregationExpression {
*
* @param expressionString must not be {@literal null}.
* @param parameters can be empty.
* @return
* @return new instance of {@link AggregationSpELExpression}.
*/
public static AggregationSpELExpression expressionOf(String expressionString, Object... parameters) {

View File

@@ -1,325 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.data.mongodb.core.aggregation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import org.bson.Document;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.SerializationUtils;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Abstraction for {@code db.collection.update()} using an aggregation pipeline. Aggregation pipeline updates use a more
* expressive update statement expressing conditional updates based on current field values or updating one field using
* the value of another field(s).
*
* <pre class="code">
* AggregationUpdate update = AggregationUpdate.update().set("average")
* .toValue(ArithmeticOperators.valueOf("tests").avg()).set("grade")
* .toValue(ConditionalOperators
* .switchCases(CaseOperator.when(Gte.valueOf("average").greaterThanEqualToValue(90)).then("A"),
* CaseOperator.when(Gte.valueOf("average").greaterThanEqualToValue(80)).then("B"),
* CaseOperator.when(Gte.valueOf("average").greaterThanEqualToValue(70)).then("C"),
* CaseOperator.when(Gte.valueOf("average").greaterThanEqualToValue(60)).then("D"))
* .defaultTo("F"));
* </pre>
*
* The above sample is equivalent to the JSON update statement:
*
* <pre class="code">
* db.collection.update(
* { },
* [
* { $set: { average : { $avg: "$tests" } } },
* { $set: { grade: { $switch: {
* branches: [
* { case: { $gte: [ "$average", 90 ] }, then: "A" },
* { case: { $gte: [ "$average", 80 ] }, then: "B" },
* { case: { $gte: [ "$average", 70 ] }, then: "C" },
* { case: { $gte: [ "$average", 60 ] }, then: "D" }
* ],
* default: "F"
* } } } }
* ],
* { multi: true }
* )
* </pre>
*
* @author Christoph Strobl
* @author Mark Paluch
* @see <a href=
* "https://docs.mongodb.com/manual/reference/method/db.collection.update/#update-with-aggregation-pipeline">MongoDB
* Reference Documentation</a>
* @since 3.0
*/
public class AggregationUpdate extends Aggregation implements UpdateDefinition {
private boolean isolated = false;
private Set<String> keysTouched = new HashSet<>();
/**
* Create new {@link AggregationUpdate}.
*/
protected AggregationUpdate() {
this(new ArrayList<>());
}
/**
* Create new {@link AggregationUpdate} with the given aggregation pipeline to apply.
*
* @param pipeline must not be {@literal null}.
*/
protected AggregationUpdate(List<AggregationOperation> pipeline) {
super(pipeline);
for (AggregationOperation operation : pipeline) {
if (operation instanceof FieldsExposingAggregationOperation) {
((FieldsExposingAggregationOperation) operation).getFields().forEach(it -> {
keysTouched.add(it.getName());
});
}
}
}
/**
* Start defining the update pipeline to execute.
*
* @return new instance of {@link AggregationUpdate}.
*/
public static AggregationUpdate update() {
return new AggregationUpdate();
}
/**
* Create a new AggregationUpdate from the given {@link AggregationOperation}s.
*
* @return new instance of {@link AggregationUpdate}.
*/
public static AggregationUpdate from(List<AggregationOperation> pipeline) {
return new AggregationUpdate(pipeline);
}
/**
* Adds new fields to documents. {@code $set} outputs documents that contain all existing fields from the input
* documents and newly added fields.
*
* @param setOperation must not be {@literal null}.
* @return this.
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/set/">$set Aggregation Reference</a>
*/
public AggregationUpdate set(SetOperation setOperation) {
Assert.notNull(setOperation, "SetOperation must not be null!");
setOperation.getFields().forEach(it -> {
keysTouched.add(it.getName());
});
operations.add(setOperation);
return this;
}
/**
* {@code $unset} removes/excludes fields from documents.
*
* @param unsetOperation must not be {@literal null}.
* @return this.
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/unset/">$unset Aggregation
* Reference</a>
*/
public AggregationUpdate unset(UnsetOperation unsetOperation) {
Assert.notNull(unsetOperation, "UnsetOperation must not be null!");
operations.add(unsetOperation);
keysTouched.addAll(unsetOperation.removedFieldNames());
return this;
}
/**
* {@code $replaceWith} replaces the input document with the specified document. The operation replaces all existing
* fields in the input document, including the <strong>_id</strong> field.
*
* @param replaceWithOperation
* @return this.
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/replaceWith/">$replaceWith Aggregation
* Reference</a>
*/
public AggregationUpdate replaceWith(ReplaceWithOperation replaceWithOperation) {
Assert.notNull(replaceWithOperation, "ReplaceWithOperation must not be null!");
operations.add(replaceWithOperation);
return this;
}
/**
* {@code $replaceWith} replaces the input document with the value.
*
* @param value must not be {@literal null}.
* @return this.
*/
public AggregationUpdate replaceWith(Object value) {
Assert.notNull(value, "Value must not be null!");
return replaceWith(ReplaceWithOperation.replaceWithValue(value));
}
/**
* Fluent API variant for {@code $set} adding a single {@link SetOperation pipeline operation} every time. To update
* multiple fields within one {@link SetOperation} use {@link #set(SetOperation)}.
*
* @param key must not be {@literal null}.
* @return new instance of {@link SetValueAppender}.
* @see #set(SetOperation)
*/
public SetValueAppender set(String key) {
Assert.notNull(key, "Key must not be null!");
return new SetValueAppender() {
@Override
public AggregationUpdate toValue(@Nullable Object value) {
return set(SetOperation.builder().set(key).toValue(value));
}
@Override
public AggregationUpdate toValueOf(Object value) {
Assert.notNull(value, "Value must not be null!");
return set(SetOperation.builder().set(key).toValueOf(value));
}
};
}
/**
* Short for {@link #unset(UnsetOperation)}.
*
* @param keys
* @return
*/
public AggregationUpdate unset(String... keys) {
Assert.notNull(keys, "Keys must not be null!");
Assert.noNullElements(keys, "Keys must not contain null elements.");
return unset(new UnsetOperation(Arrays.stream(keys).map(Fields::field).collect(Collectors.toList())));
}
/**
* Prevents a write operation that affects <strong>multiple</strong> documents from yielding to other reads or writes
* once the first document is written. <br />
* Use with {@link org.springframework.data.mongodb.core.MongoOperations#updateMulti(Query, UpdateDefinition, Class)}.
*
* @return never {@literal null}.
*/
public AggregationUpdate isolated() {
isolated = true;
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.query.UpdateDefinition#isIsolated()
*/
@Override
public Boolean isIsolated() {
return isolated;
}
/*
* Returns a update document containing the update pipeline.
* The resulting document needs to be unwrapped to be used with update operations.
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.query.UpdateDefinition#getUpdateObject()
*/
@Override
public Document getUpdateObject() {
return new Document("", toPipeline(Aggregation.DEFAULT_CONTEXT));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.query.UpdateDefinition#modifies(java.lang.String)
*/
@Override
public boolean modifies(String key) {
return keysTouched.contains(key);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.query.UpdateDefinition#inc(java.lang.String)
*/
@Override
public void inc(String key) {
set(new SetOperation(key, ArithmeticOperators.valueOf(key).add(1)));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.query.UpdateDefinition#getArrayFilters()
*/
@Override
public List<ArrayFilter> getArrayFilters() {
return Collections.emptyList();
}
@Override
public String toString() {
StringJoiner joiner = new StringJoiner(",\n", "[\n", "\n]");
toPipeline(Aggregation.DEFAULT_CONTEXT).stream().map(SerializationUtils::serializeToJsonSafely)
.forEach(joiner::add);
return joiner.toString();
}
/**
* Fluent API AggregationUpdate builder.
*
* @author Christoph Strobl
*/
public interface SetValueAppender {
/**
* Define the target value as is.
*
* @param value can be {@literal null}.
* @return never {@literal null}.
*/
AggregationUpdate toValue(@Nullable Object value);
/**
* Define the target value as value, an {@link AggregationExpression} or a {@link Field} reference.
*
* @param value can be {@literal null}.
* @return never {@literal null}.
*/
AggregationUpdate toValueOf(Object value);
}
}

View File

@@ -32,9 +32,9 @@ interface AggregationUtils {
* Converts the given {@link Range} into an array of values.
*
* @param range must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
public static List<Long> toRangeValues(Range<Long> range) {
static List<Long> toRangeValues(Range<Long> range) {
Assert.notNull(range, "Range must not be null!");

View File

@@ -43,7 +43,7 @@ public class ArrayOperators {
* Take the array referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ArrayOperatorFactory}.
*/
public static ArrayOperatorFactory arrayOf(String fieldReference) {
return new ArrayOperatorFactory(fieldReference);
@@ -53,7 +53,7 @@ public class ArrayOperators {
* Take the array referenced resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ArrayOperatorFactory}.
*/
public static ArrayOperatorFactory arrayOf(AggregationExpression expression) {
return new ArrayOperatorFactory(expression);
@@ -123,8 +123,8 @@ public class ArrayOperators {
* Creates new {@link AggregationExpression} that takes the associated array and returns the element at the
* specified array {@literal position}.
*
* @param position
* @return
* @param position the element index.
* @return new instance of {@link ArrayElemAt}.
*/
public ArrayElemAt elementAt(int position) {
return createArrayElemAt().elementAt(position);
@@ -135,7 +135,7 @@ public class ArrayOperators {
* resulting form the given {@literal expression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ArrayElemAt}.
*/
public ArrayElemAt elementAt(AggregationExpression expression) {
@@ -148,7 +148,7 @@ public class ArrayOperators {
* defined by the referenced {@literal field}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ArrayElemAt}.
*/
public ArrayElemAt elementAt(String fieldReference) {
@@ -170,7 +170,7 @@ public class ArrayOperators {
* {@literal arrayFieldReference} to it.
*
* @param arrayFieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ConcatArrays}.
*/
public ConcatArrays concat(String arrayFieldReference) {
@@ -183,7 +183,7 @@ public class ArrayOperators {
* the given {@literal expression} to it.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ConcatArrays}.
*/
public ConcatArrays concat(AggregationExpression expression) {
@@ -204,7 +204,7 @@ public class ArrayOperators {
* Creates new {@link AggregationExpression} that takes the associated array and selects a subset of the array to
* return based on the specified condition.
*
* @return
* @return new instance of {@link AsBuilder} to create a {@link Filter}.
*/
public AsBuilder filter() {
@@ -219,7 +219,7 @@ public class ArrayOperators {
/**
* Creates new {@link AggregationExpression} that takes the associated array and an check if its an array.
*
* @return
* @return new instance of {@link IsArray}.
*/
public IsArray isArray() {
@@ -231,7 +231,7 @@ public class ArrayOperators {
/**
* Creates new {@link AggregationExpression} that takes the associated array and retrieves its length.
*
* @return
* @return new instance of {@link Size}.
*/
public Size length() {
@@ -245,7 +245,7 @@ public class ArrayOperators {
/**
* Creates new {@link AggregationExpression} that takes the associated array and selects a subset from it.
*
* @return
* @return new instance of {@link Slice}.
*/
public Slice slice() {
@@ -261,7 +261,7 @@ public class ArrayOperators {
* value and returns the array index (zero-based) of the first occurrence.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfArray}.
*/
public IndexOfArray indexOf(Object value) {
@@ -276,7 +276,7 @@ public class ArrayOperators {
/**
* Creates new {@link AggregationExpression} that returns an array with the elements in reverse order.
*
* @return
* @return new instance of {@link ReverseArray}.
*/
public ReverseArray reverse() {
@@ -293,7 +293,7 @@ public class ArrayOperators {
* an array and combines them into a single value.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ReduceInitialValueBuilder} to create {@link Reduce}.
*/
public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(AggregationExpression expression) {
@@ -305,8 +305,8 @@ public class ArrayOperators {
* Start creating new {@link AggregationExpression} that applies an {@link AggregationExpression} to each element in
* an array and combines them into a single value.
*
* @param expressions
* @return
* @param expressions must not be {@literal null}.
* @return new instance of {@link ReduceInitialValueBuilder} to create {@link Reduce}.
*/
public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(PropertyExpression... expressions) {
@@ -320,7 +320,7 @@ public class ArrayOperators {
* the second input array, etc.
*
* @param arrays must not be {@literal null}.
* @return
* @return new instance of {@link Zip}.
*/
public Zip zipWith(Object... arrays) {
@@ -336,7 +336,7 @@ public class ArrayOperators {
* associated array.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link In}.
*/
public In containsValue(Object value) {
@@ -413,7 +413,7 @@ public class ArrayOperators {
* Creates new {@link ArrayElemAt}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ArrayElemAt}.
*/
public static ArrayElemAt arrayOf(String fieldReference) {
@@ -425,7 +425,7 @@ public class ArrayOperators {
* Creates new {@link ArrayElemAt}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ArrayElemAt}.
*/
public static ArrayElemAt arrayOf(AggregationExpression expression) {
@@ -446,16 +446,34 @@ public class ArrayOperators {
return new ArrayElemAt(Collections.singletonList(values));
}
/**
* Use the element with given index number.
*
* @param index the index number
* @return new instance of {@link ArrayElemAt}.
*/
public ArrayElemAt elementAt(int index) {
return new ArrayElemAt(append(index));
}
/**
* Use the element at the index number evaluated from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link ArrayElemAt}.
*/
public ArrayElemAt elementAt(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new ArrayElemAt(append(expression));
}
/**
* Use the element at the index number traken from the given field.
*
* @param arrayFieldReference the field name.
* @return new instance of {@link ArrayElemAt}.
*/
public ArrayElemAt elementAt(String arrayFieldReference) {
Assert.notNull(arrayFieldReference, "ArrayReference must not be null!");
@@ -483,7 +501,7 @@ public class ArrayOperators {
* Creates new {@link ConcatArrays}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ConcatArrays}.
*/
public static ConcatArrays arrayOf(String fieldReference) {
@@ -495,7 +513,7 @@ public class ArrayOperators {
* Creates new {@link ConcatArrays}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ConcatArrays}.
*/
public static ConcatArrays arrayOf(AggregationExpression expression) {
@@ -516,12 +534,24 @@ public class ArrayOperators {
return new ConcatArrays(Collections.singletonList(values));
}
/**
* Concat with the array stored at the given field.
*
* @param arrayFieldReference must not be {@literal null}.
* @return new instance of {@link ConcatArrays}.
*/
public ConcatArrays concat(String arrayFieldReference) {
Assert.notNull(arrayFieldReference, "ArrayFieldReference must not be null!");
return new ConcatArrays(append(Fields.field(arrayFieldReference)));
}
/**
* Concat with the array resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link ConcatArrays}.
*/
public ConcatArrays concat(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
@@ -574,7 +604,7 @@ public class ArrayOperators {
* Set the {@literal values} to apply the {@code $filter} to.
*
* @param values must not be {@literal null}.
* @return
* @return new instance of {@link AsBuilder} to create the {@link Filter}.
*/
public static AsBuilder filter(List<?> values) {
@@ -651,7 +681,7 @@ public class ArrayOperators {
* Set the {@literal variableName} for the elements in the input array.
*
* @param variableName must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
ConditionBuilder as(String variableName);
}
@@ -665,7 +695,7 @@ public class ArrayOperators {
* Set the {@link AggregationExpression} that determines whether to include the element in the resulting array.
*
* @param expression must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
Filter by(AggregationExpression expression);
@@ -673,7 +703,7 @@ public class ArrayOperators {
* Set the {@literal expression} that determines whether to include the element in the resulting array.
*
* @param expression must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
Filter by(String expression);
@@ -681,7 +711,7 @@ public class ArrayOperators {
* Set the {@literal expression} that determines whether to include the element in the resulting array.
*
* @param expression must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
Filter by(Document expression);
}
@@ -700,7 +730,7 @@ public class ArrayOperators {
/**
* Creates new {@link InputBuilder}.
*
* @return
* @return new instance of {@link FilterExpressionBuilder}.
*/
public static InputBuilder newBuilder() {
return new FilterExpressionBuilder();
@@ -800,7 +830,7 @@ public class ArrayOperators {
* Creates new {@link IsArray}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IsArray}.
*/
public static IsArray isArray(String fieldReference) {
@@ -812,7 +842,7 @@ public class ArrayOperators {
* Creates new {@link IsArray}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IsArray}.
*/
public static IsArray isArray(AggregationExpression expression) {
@@ -841,7 +871,7 @@ public class ArrayOperators {
* Creates new {@link Size}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Size}.
*/
public static Size lengthOfArray(String fieldReference) {
@@ -853,7 +883,7 @@ public class ArrayOperators {
* Creates new {@link Size}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Size}.
*/
public static Size lengthOfArray(AggregationExpression expression) {
@@ -895,7 +925,7 @@ public class ArrayOperators {
* Creates new {@link Slice}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Slice}.
*/
public static Slice sliceArrayOf(String fieldReference) {
@@ -907,7 +937,7 @@ public class ArrayOperators {
* Creates new {@link Slice}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Slice}.
*/
public static Slice sliceArrayOf(AggregationExpression expression) {
@@ -928,10 +958,22 @@ public class ArrayOperators {
return new Slice(Collections.singletonList(values));
}
/**
* Slice the number of elements.
*
* @param nrElements elements to slice.
* @return new instance of {@link Slice}.
*/
public Slice itemCount(int nrElements) {
return new Slice(append(nrElements));
}
/**
* Slice using offset and count.
*
* @param position the start position
* @return new instance of {@link SliceElementsBuilder} to create {@link Slice}.
*/
public SliceElementsBuilder offset(final int position) {
return new SliceElementsBuilder() {
@@ -978,7 +1020,7 @@ public class ArrayOperators {
* Start creating new {@link IndexOfArray}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfArray}.
*/
public static IndexOfArrayBuilder arrayOf(String fieldReference) {
@@ -990,7 +1032,7 @@ public class ArrayOperators {
* Start creating new {@link IndexOfArray}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfArray}.
*/
public static IndexOfArrayBuilder arrayOf(AggregationExpression expression) {
@@ -1002,7 +1044,7 @@ public class ArrayOperators {
* Start creating new {@link IndexOfArray}.
*
* @param values must not be {@literal null}.
* @return new instance of {@link IndexOfArray}.
* @return new instance of {@link IndexOfArrayBuilder} to create {@link IndexOfArray}.
* @since 2.2
*/
public static IndexOfArrayBuilder arrayOf(Collection<?> values) {
@@ -1011,6 +1053,12 @@ public class ArrayOperators {
return new IndexOfArrayBuilder(values);
}
/**
* Lookup within a given range.
*
* @param range the lookup range.
* @return new instance of {@link IndexOfArray}.
*/
public IndexOfArray within(Range<Long> range) {
return new IndexOfArray(append(AggregationUtils.toRangeValues(range)));
}
@@ -1030,7 +1078,7 @@ public class ArrayOperators {
* Set the {@literal value} to check for its index in the array.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfArray}.
*/
public IndexOfArray indexOf(Object value) {
@@ -1060,7 +1108,7 @@ public class ArrayOperators {
* Start creating new {@link RangeOperator}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link RangeOperatorBuilder} to create {@link RangeOperator}.
*/
public static RangeOperatorBuilder rangeStartingAt(String fieldReference) {
return new RangeOperatorBuilder(Fields.field(fieldReference));
@@ -1070,7 +1118,7 @@ public class ArrayOperators {
* Start creating new {@link RangeOperator}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link RangeOperatorBuilder} to create {@link RangeOperator}.
*/
public static RangeOperatorBuilder rangeStartingAt(AggregationExpression expression) {
return new RangeOperatorBuilder(expression);
@@ -1080,7 +1128,7 @@ public class ArrayOperators {
* Start creating new {@link RangeOperator}.
*
* @param value
* @return
* @return new instance of {@link RangeOperator}.
*/
public static RangeOperatorBuilder rangeStartingAt(long value) {
return new RangeOperatorBuilder(value);
@@ -1102,7 +1150,7 @@ public class ArrayOperators {
* Creates new {@link RangeOperator}.
*
* @param index
* @return
* @return new instance of {@link RangeOperator}.
*/
public RangeOperator to(long index) {
return new RangeOperator(Arrays.asList(startPoint, index));
@@ -1112,7 +1160,7 @@ public class ArrayOperators {
* Creates new {@link RangeOperator}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link RangeOperator}.
*/
public RangeOperator to(AggregationExpression expression) {
return new RangeOperator(Arrays.asList(startPoint, expression));
@@ -1122,7 +1170,7 @@ public class ArrayOperators {
* Creates new {@link RangeOperator}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link RangeOperator}.
*/
public RangeOperator to(String fieldReference) {
return new RangeOperator(Arrays.asList(startPoint, Fields.field(fieldReference)));
@@ -1150,7 +1198,7 @@ public class ArrayOperators {
* Creates new {@link ReverseArray} given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ReverseArray}.
*/
public static ReverseArray reverseArrayOf(String fieldReference) {
return new ReverseArray(Fields.field(fieldReference));
@@ -1160,7 +1208,7 @@ public class ArrayOperators {
* Creates new {@link ReverseArray} given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ReverseArray}.
*/
public static ReverseArray reverseArrayOf(AggregationExpression expression) {
return new ReverseArray(expression);
@@ -1239,7 +1287,7 @@ public class ArrayOperators {
* Start creating new {@link Reduce}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link InitialValueBuilder} to create {@link Reduce}.
*/
public static InitialValueBuilder arrayOf(final String fieldReference) {
@@ -1278,7 +1326,7 @@ public class ArrayOperators {
* Start creating new {@link Reduce}.
*
* @param arrayValueExpression must not be {@literal null}.
* @return
* @return new instance of {@link InitialValueBuilder} to create {@link Reduce}.
*/
public static InitialValueBuilder arrayOf(final AggregationExpression arrayValueExpression) {
@@ -1318,7 +1366,7 @@ public class ArrayOperators {
* Define the initial cumulative value set before in is applied to the first element of the input array.
*
* @param initialValue must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
ReduceBuilder withInitialValue(Object initialValue);
}
@@ -1335,7 +1383,7 @@ public class ArrayOperators {
* {@link Variable#VALUE} are available.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Reduce}.
*/
Reduce reduce(AggregationExpression expression);
@@ -1346,7 +1394,7 @@ public class ArrayOperators {
* {@link Variable#VALUE} are available.
*
* @param expressions must not be {@literal null}.
* @return
* @return new instance of {@link Reduce}.
*/
Reduce reduce(PropertyExpression... expressions);
}
@@ -1372,7 +1420,7 @@ public class ArrayOperators {
* Define a result property for an {@link AggregationExpression} used in {@link Reduce}.
*
* @param name must not be {@literal null}.
* @return
* @return new instance of {@link AsBuilder} to create {@link Reduce}.
*/
public static AsBuilder property(final String name) {
@@ -1402,7 +1450,7 @@ public class ArrayOperators {
* Set the {@link AggregationExpression} resulting in the properties value.
*
* @param expression must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
PropertyExpression definedAs(AggregationExpression expression);
}
@@ -1459,7 +1507,7 @@ public class ArrayOperators {
* eg. {@code $$value.product}
*
* @param property must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
public Field referringTo(final String property) {
@@ -1508,7 +1556,7 @@ public class ArrayOperators {
* Start creating new {@link Zip}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ZipBuilder} to create {@link Zip}.
*/
public static ZipBuilder arrayOf(String fieldReference) {
@@ -1520,7 +1568,7 @@ public class ArrayOperators {
* Start creating new {@link Zip}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ZipBuilder} to create {@link Zip}.
*/
public static ZipBuilder arrayOf(AggregationExpression expression) {
@@ -1544,7 +1592,7 @@ public class ArrayOperators {
/**
* Create new {@link Zip} and set the {@code useLongestLength} property to {@literal true}.
*
* @return
* @return new instance of {@link Zip}.
*/
public Zip useLongestLength() {
return new Zip(append("useLongestLength", true));
@@ -1554,7 +1602,7 @@ public class ArrayOperators {
* Optionally provide a default value.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Zip}.
*/
public Zip defaultTo(String fieldReference) {
@@ -1566,7 +1614,7 @@ public class ArrayOperators {
* Optionally provide a default value.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Zip}.
*/
public Zip defaultTo(AggregationExpression expression) {
@@ -1578,7 +1626,7 @@ public class ArrayOperators {
* Optionally provide a default value.
*
* @param array must not be {@literal null}.
* @return
* @return new instance of {@link Zip}.
*/
public Zip defaultTo(Object[] array) {
@@ -1602,7 +1650,7 @@ public class ArrayOperators {
* array, etc.
*
* @param arrays arrays to zip the referenced one with. must not be {@literal null}.
* @return
* @return new instance of {@link Zip}.
*/
public Zip zip(Object... arrays) {
@@ -1645,7 +1693,7 @@ public class ArrayOperators {
* Start creating {@link In}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link InBuilder} to create {@link In}.
*/
public static InBuilder arrayOf(String fieldReference) {
@@ -1662,7 +1710,7 @@ public class ArrayOperators {
* Start creating {@link In}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link InBuilder} to create {@link In}.
*/
public static InBuilder arrayOf(AggregationExpression expression) {
@@ -1704,7 +1752,7 @@ public class ArrayOperators {
* Set the {@literal value} to check for existence in the array.
*
* @param value must not be {@literal value}.
* @return
* @return new instance of {@link In}.
*/
In containsValue(Object value);
}

View File

@@ -34,7 +34,7 @@ public class BooleanOperators {
* Take the array referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link BooleanOperatorFactory}.
*/
public static BooleanOperatorFactory valueOf(String fieldReference) {
return new BooleanOperatorFactory(fieldReference);
@@ -44,7 +44,7 @@ public class BooleanOperators {
* Take the value resulting of the given {@link AggregationExpression}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link BooleanOperatorFactory}.
*/
public static BooleanOperatorFactory valueOf(AggregationExpression fieldReference) {
return new BooleanOperatorFactory(fieldReference);
@@ -55,7 +55,7 @@ public class BooleanOperators {
* opposite boolean value.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Not}.
*/
public static Not not(String fieldReference) {
return Not.not(fieldReference);
@@ -66,7 +66,7 @@ public class BooleanOperators {
* and returns the opposite boolean value.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Not}.
*/
public static Not not(AggregationExpression expression) {
return Not.not(expression);
@@ -109,7 +109,7 @@ public class BooleanOperators {
* all of the expressions are {@literal true}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link And}.
*/
public And and(AggregationExpression expression) {
@@ -122,7 +122,7 @@ public class BooleanOperators {
* all of the expressions are {@literal true}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link And}.
*/
public And and(String fieldReference) {
@@ -139,7 +139,7 @@ public class BooleanOperators {
* any of the expressions are {@literal true}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Or}.
*/
public Or or(AggregationExpression expression) {
@@ -152,7 +152,7 @@ public class BooleanOperators {
* any of the expressions are {@literal true}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Or}.
*/
public Or or(String fieldReference) {
@@ -167,7 +167,7 @@ public class BooleanOperators {
/**
* Creates new {@link AggregationExpression} that evaluates a boolean and returns the opposite boolean value.
*
* @return
* @return new instance of {@link Not}.
*/
public Not not() {
return usesFieldRef() ? Not.not(fieldReference) : Not.not(expression);
@@ -198,8 +198,8 @@ public class BooleanOperators {
* Creates new {@link And} that evaluates one or more expressions and returns {@literal true} if all of the
* expressions are {@literal true}.
*
* @param expressions
* @return
* @param expressions must not be {@literal null}.
* @return new instance of {@link And}.
*/
public static And and(Object... expressions) {
return new And(Arrays.asList(expressions));
@@ -209,7 +209,7 @@ public class BooleanOperators {
* Creates new {@link And} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link And}.
*/
public And andExpression(AggregationExpression expression) {
@@ -221,7 +221,7 @@ public class BooleanOperators {
* Creates new {@link And} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link And}.
*/
public And andField(String fieldReference) {
@@ -233,7 +233,7 @@ public class BooleanOperators {
* Creates new {@link And} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link And}.
*/
public And andValue(Object value) {
@@ -263,7 +263,7 @@ public class BooleanOperators {
* expressions are {@literal true}.
*
* @param expressions must not be {@literal null}.
* @return
* @return new instance of {@link Or}.
*/
public static Or or(Object... expressions) {
@@ -275,7 +275,7 @@ public class BooleanOperators {
* Creates new {@link Or} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Or}.
*/
public Or orExpression(AggregationExpression expression) {
@@ -287,7 +287,7 @@ public class BooleanOperators {
* Creates new {@link Or} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Or}.
*/
public Or orField(String fieldReference) {
@@ -299,7 +299,7 @@ public class BooleanOperators {
* Creates new {@link Or} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Or}.
*/
public Or orValue(Object value) {
@@ -329,7 +329,7 @@ public class BooleanOperators {
* value.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Not}.
*/
public static Not not(String fieldReference) {
@@ -342,7 +342,7 @@ public class BooleanOperators {
* returns the opposite boolean value.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Not}.
*/
public static Not not(AggregationExpression expression) {

View File

@@ -15,12 +15,12 @@
*/
package org.springframework.data.mongodb.core.aggregation;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.BucketAutoOperation.BucketAutoOperationOutputBuilder;
import org.springframework.data.mongodb.core.aggregation.BucketOperationSupport.OutputBuilder;
import org.springframework.util.Assert;
import org.bson.Document;
/**
* Encapsulates the aggregation framework {@code $bucketAuto}-operation. <br />
* Bucket stage is typically used with {@link Aggregation} and {@code $facet}. Categorizes incoming documents into a
@@ -113,7 +113,7 @@ public class BucketAutoOperation extends BucketOperationSupport<BucketAutoOperat
* Configures a number of bucket {@literal buckets} and return a new {@link BucketAutoOperation}.
*
* @param buckets must be a positive number.
* @return
* @return new instance of {@link BucketAutoOperation}.
*/
public BucketAutoOperation withBuckets(int buckets) {
@@ -128,7 +128,7 @@ public class BucketAutoOperation extends BucketOperationSupport<BucketAutoOperat
* Use either predefined {@link Granularities} or provide a own one.
*
* @param granularity must not be {@literal null}.
* @return
* @return new instance of {@link BucketAutoOperation}.
*/
public BucketAutoOperation withGranularity(Granularity granularity) {
@@ -209,7 +209,7 @@ public class BucketAutoOperation extends BucketOperationSupport<BucketAutoOperat
*
* @param expression must not be {@literal null}.
* @param operation must not be {@literal null}.
* @param parameters
* @param parameters must not be {@literal null}.
*/
protected ExpressionBucketAutoOperationBuilder(String expression, BucketAutoOperation operation,
Object[] parameters) {

View File

@@ -20,11 +20,11 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.BucketOperation.BucketOperationOutputBuilder;
import org.springframework.util.Assert;
import org.bson.Document;
/**
* Encapsulates the aggregation framework {@code $bucket}-operation. <br />
*
@@ -110,7 +110,7 @@ public class BucketOperation extends BucketOperationSupport<BucketOperation, Buc
* Configures a default bucket {@literal literal} and return a new {@link BucketOperation}.
*
* @param literal must not be {@literal null}.
* @return
* @return new instance of {@link BucketOperation}.
*/
public BucketOperation withDefaultBucket(Object literal) {
@@ -123,7 +123,7 @@ public class BucketOperation extends BucketOperationSupport<BucketOperation, Buc
* preserved and the new {@literal boundaries} are appended.
*
* @param boundaries must not be {@literal null}.
* @return
* @return new instance of {@link BucketOperation}.
*/
public BucketOperation withBoundaries(Object... boundaries) {
@@ -204,12 +204,12 @@ public class BucketOperation extends BucketOperationSupport<BucketOperation, Buc
extends ExpressionBucketOperationBuilderSupport<BucketOperationOutputBuilder, BucketOperation> {
/**
* Creates a new {@link ExpressionBucketOperationBuilderSupport} for the given value, {@link BucketOperation}
* and parameters.
* Creates a new {@link ExpressionBucketOperationBuilderSupport} for the given value, {@link BucketOperation} and
* parameters.
*
* @param expression must not be {@literal null}.
* @param operation must not be {@literal null}.
* @param parameters
* @param parameters must not be {@literal null}.
*/
protected ExpressionBucketOperationBuilder(String expression, BucketOperation operation, Object[] parameters) {
super(expression, operation, parameters);

View File

@@ -21,14 +21,13 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.BucketOperationSupport.OutputBuilder;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder;
import org.springframework.expression.spel.ast.Projection;
import org.springframework.util.Assert;
import org.bson.Document;
/**
* Base class for bucket operations that support output expressions the aggregation framework. <br />
* Bucket stages collect documents into buckets and can contribute output fields. <br />
@@ -104,7 +103,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
*
* @param expression the SpEL expression, must not be {@literal null} or empty.
* @param params must not be {@literal null}
* @return
* @return new instance of {@link ExpressionBucketOperationBuilderSupport} to create {@link BucketOperation}.
*/
public abstract ExpressionBucketOperationBuilderSupport<B, T> andOutputExpression(String expression,
Object... params);
@@ -114,7 +113,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
* resulting bucket documents.
*
* @param expression the SpEL expression, must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
*/
public abstract B andOutput(AggregationExpression expression);
@@ -124,14 +123,14 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
* {@literal fieldName}.
*
* @param fieldName must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
*/
public abstract B andOutput(String fieldName);
/**
* Creates a new {@link BucketOperationSupport} given to add a count field to the resulting bucket documents.
*
* @return
* @return never {@literal null}.
*/
public B andOutputCount() {
return andOutput(new AggregationExpression() {
@@ -231,7 +230,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
* Generates a builder for a {@code $sum}-expression. <br />
* Count expressions are emulated via {@code $sum: 1}.
*
* @return
* @return never {@literal null}.
*/
public B count() {
return sum(1);
@@ -240,7 +239,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for a {@code $sum}-expression for the current value.
*
* @return
* @return never {@literal null}.
*/
public B sum() {
return apply(Accumulators.SUM);
@@ -249,8 +248,8 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for a {@code $sum}-expression for the given {@literal value}.
*
* @param value
* @return
* @param value must not be {@literal null}.
* @return never {@literal null}.
*/
public B sum(Number value) {
return apply(new OperationOutput(Accumulators.SUM.getMongoOperator(), Collections.singleton(value)));
@@ -259,7 +258,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for an {@code $last}-expression for the current value..
*
* @return
* @return never {@literal null}.
*/
public B last() {
return apply(Accumulators.LAST);
@@ -268,7 +267,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for a {@code $first}-expression the current value.
*
* @return
* @return never {@literal null}.
*/
public B first() {
return apply(Accumulators.FIRST);
@@ -277,8 +276,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for an {@code $avg}-expression for the current value.
*
* @param reference
* @return
* @return never {@literal null}.
*/
public B avg() {
return apply(Accumulators.AVG);
@@ -287,7 +285,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for an {@code $min}-expression for the current value.
*
* @return
* @return never {@literal null}.
*/
public B min() {
return apply(Accumulators.MIN);
@@ -296,7 +294,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for an {@code $max}-expression for the current value.
*
* @return
* @return never {@literal null}.
*/
public B max() {
return apply(Accumulators.MAX);
@@ -305,7 +303,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for an {@code $push}-expression for the current value.
*
* @return
* @return never {@literal null}.
*/
public B push() {
return apply(Accumulators.PUSH);
@@ -314,7 +312,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Generates a builder for an {@code $addToSet}-expression for the current value.
*
* @return
* @return never {@literal null}.
*/
public B addToSet() {
return apply(Accumulators.ADDTOSET);
@@ -325,7 +323,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
*
* @param operation the operation name, must not be {@literal null} or empty.
* @param values must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
public B apply(String operation, Object... values) {
@@ -342,7 +340,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
* Apply an {@link OperationOutput} to this output.
*
* @param operationOutput must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
protected abstract B apply(OperationOutput operationOutput);
@@ -354,7 +352,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
* Returns the finally to be applied {@link BucketOperation} with the given alias.
*
* @param alias will never be {@literal null} or empty.
* @return
* @return never {@literal null}.
*/
public T as(String alias) {
@@ -550,8 +548,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
public Document toDocument(AggregationOperationContext context) {
List<Object> operationArguments = getOperationArguments(context);
return new Document(operation,
operationArguments.size() == 1 ? operationArguments.get(0) : operationArguments);
return new Document(operation, operationArguments.size() == 1 ? operationArguments.get(0) : operationArguments);
}
protected List<Object> getOperationArguments(AggregationOperationContext context) {
@@ -579,7 +576,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Returns the field that holds the {@link ProjectionOperationBuilder.OperationProjection}.
*
* @return
* @return never {@literal null}.
*/
protected Field getField() {
return getExposedField();
@@ -589,7 +586,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
* Creates a new instance of this {@link OperationOutput} with the given alias.
*
* @param alias the alias to set
* @return
* @return new instance of {@link OperationOutput}.
*/
public OperationOutput withAlias(String alias) {
@@ -658,8 +655,8 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
/**
* Creates a new {@link AggregationExpressionOutput}.
*
* @param field
* @param expression
* @param field must not be {@literal null}.
* @param expression must not be {@literal null}.
*/
protected AggregationExpressionOutput(Field field, AggregationExpression expression) {

View File

@@ -32,7 +32,7 @@ public class ComparisonOperators {
* Take the field referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ComparisonOperatorFactory}.
*/
public static ComparisonOperatorFactory valueOf(String fieldReference) {
return new ComparisonOperatorFactory(fieldReference);
@@ -42,7 +42,7 @@ public class ComparisonOperators {
* Take the value resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ComparisonOperatorFactory}.
*/
public static ComparisonOperatorFactory valueOf(AggregationExpression expression) {
return new ComparisonOperatorFactory(expression);
@@ -81,7 +81,7 @@ public class ComparisonOperators {
* Creates new {@link AggregationExpression} that compares two values.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Cmp}.
*/
public Cmp compareTo(String fieldReference) {
return createCmp().compareTo(fieldReference);
@@ -91,7 +91,7 @@ public class ComparisonOperators {
* Creates new {@link AggregationExpression} that compares two values.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Cmp}.
*/
public Cmp compareTo(AggregationExpression expression) {
return createCmp().compareTo(expression);
@@ -101,7 +101,7 @@ public class ComparisonOperators {
* Creates new {@link AggregationExpression} that compares two values.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Cmp}.
*/
public Cmp compareToValue(Object value) {
return createCmp().compareToValue(value);
@@ -116,7 +116,7 @@ public class ComparisonOperators {
* value is equal to the value of the referenced field.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Eq}.
*/
public Eq equalTo(String fieldReference) {
return createEq().equalTo(fieldReference);
@@ -127,7 +127,7 @@ public class ComparisonOperators {
* value is equal to the expression result.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Eq}.
*/
public Eq equalTo(AggregationExpression expression) {
return createEq().equalTo(expression);
@@ -138,7 +138,7 @@ public class ComparisonOperators {
* value is equal to the given value.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Eq}.
*/
public Eq equalToValue(Object value) {
return createEq().equalToValue(value);
@@ -153,7 +153,7 @@ public class ComparisonOperators {
* value is greater than the value of the referenced field.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Gt}.
*/
public Gt greaterThan(String fieldReference) {
return createGt().greaterThan(fieldReference);
@@ -164,7 +164,7 @@ public class ComparisonOperators {
* value is greater than the expression result.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Gt}.
*/
public Gt greaterThan(AggregationExpression expression) {
return createGt().greaterThan(expression);
@@ -175,7 +175,7 @@ public class ComparisonOperators {
* value is greater than the given value.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Gt}.
*/
public Gt greaterThanValue(Object value) {
return createGt().greaterThanValue(value);
@@ -190,7 +190,7 @@ public class ComparisonOperators {
* value is greater than or equivalent to the value of the referenced field.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Gte}.
*/
public Gte greaterThanEqualTo(String fieldReference) {
return createGte().greaterThanEqualTo(fieldReference);
@@ -201,7 +201,7 @@ public class ComparisonOperators {
* value is greater than or equivalent to the expression result.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Gte}.
*/
public Gte greaterThanEqualTo(AggregationExpression expression) {
return createGte().greaterThanEqualTo(expression);
@@ -212,7 +212,7 @@ public class ComparisonOperators {
* value is greater than or equivalent to the given value.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Gte}.
*/
public Gte greaterThanEqualToValue(Object value) {
return createGte().greaterThanEqualToValue(value);
@@ -227,7 +227,7 @@ public class ComparisonOperators {
* value is less than the value of the referenced field.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Lt}.
*/
public Lt lessThan(String fieldReference) {
return createLt().lessThan(fieldReference);
@@ -238,7 +238,7 @@ public class ComparisonOperators {
* value is less than the expression result.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Lt}.
*/
public Lt lessThan(AggregationExpression expression) {
return createLt().lessThan(expression);
@@ -249,7 +249,7 @@ public class ComparisonOperators {
* value is less than to the given value.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Lt}.
*/
public Lt lessThanValue(Object value) {
return createLt().lessThanValue(value);
@@ -264,7 +264,7 @@ public class ComparisonOperators {
* value is less than or equivalent to the value of the referenced field.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Lte}.
*/
public Lte lessThanEqualTo(String fieldReference) {
return createLte().lessThanEqualTo(fieldReference);
@@ -275,7 +275,7 @@ public class ComparisonOperators {
* value is less than or equivalent to the expression result.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Lte}.
*/
public Lte lessThanEqualTo(AggregationExpression expression) {
return createLte().lessThanEqualTo(expression);
@@ -285,8 +285,8 @@ public class ComparisonOperators {
* Creates new {@link AggregationExpression} that compares two values and returns {@literal true} when the first
* value is less than or equivalent to the given value.
*
* @param value
* @return
* @param value must not be {@literal null}.
* @return new instance of {@link Lte}.
*/
public Lte lessThanEqualToValue(Object value) {
return createLte().lessThanEqualToValue(value);
@@ -301,7 +301,7 @@ public class ComparisonOperators {
* are not equivalent.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Ne}.
*/
public Ne notEqualTo(String fieldReference) {
return createNe().notEqualTo(fieldReference);
@@ -312,7 +312,7 @@ public class ComparisonOperators {
* are not equivalent.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Ne}.
*/
public Ne notEqualTo(AggregationExpression expression) {
return createNe().notEqualTo(expression);
@@ -323,7 +323,7 @@ public class ComparisonOperators {
* are not equivalent.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Ne}.
*/
public Ne notEqualToValue(Object value) {
return createNe().notEqualToValue(value);
@@ -358,7 +358,7 @@ public class ComparisonOperators {
* Creates new {@link Cmp}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Cmp}.
*/
public static Cmp valueOf(String fieldReference) {
@@ -370,7 +370,7 @@ public class ComparisonOperators {
* Creates new {@link Cmp}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Cmp}.
*/
public static Cmp valueOf(AggregationExpression expression) {
@@ -382,7 +382,7 @@ public class ComparisonOperators {
* Creates new {@link Cmp} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Cmp}.
*/
public Cmp compareTo(String fieldReference) {
@@ -394,7 +394,7 @@ public class ComparisonOperators {
* Creates new {@link Cmp} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Cmp}.
*/
public Cmp compareTo(AggregationExpression expression) {
@@ -406,12 +406,12 @@ public class ComparisonOperators {
* Creates new {@link Cmp} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Cmp}.
*/
public Cmp compareToValue(Object value) {
Assert.notNull(value, "Value must not be null!");
return new Cmp(append(value));
return new Cmp(append(value, Expand.KEEP_SOURCE));
}
}
@@ -435,7 +435,7 @@ public class ComparisonOperators {
* Creates new {@link Eq}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Eq}.
*/
public static Eq valueOf(String fieldReference) {
@@ -447,7 +447,7 @@ public class ComparisonOperators {
* Creates new {@link Eq}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Eq}.
*/
public static Eq valueOf(AggregationExpression expression) {
@@ -459,7 +459,7 @@ public class ComparisonOperators {
* Creates new {@link Eq} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Eq}.
*/
public Eq equalTo(String fieldReference) {
@@ -471,7 +471,7 @@ public class ComparisonOperators {
* Creates new {@link Eq} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Eq}.
*/
public Eq equalTo(AggregationExpression expression) {
@@ -483,12 +483,12 @@ public class ComparisonOperators {
* Creates new {@link Eq} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Eq}.
*/
public Eq equalToValue(Object value) {
Assert.notNull(value, "Value must not be null!");
return new Eq(append(value));
return new Eq(append(value, Expand.KEEP_SOURCE));
}
}
@@ -512,7 +512,7 @@ public class ComparisonOperators {
* Creates new {@link Gt}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Gt}.
*/
public static Gt valueOf(String fieldReference) {
@@ -524,7 +524,7 @@ public class ComparisonOperators {
* Creates new {@link Gt}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Gt}.
*/
public static Gt valueOf(AggregationExpression expression) {
@@ -536,7 +536,7 @@ public class ComparisonOperators {
* Creates new {@link Gt} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Gt}.
*/
public Gt greaterThan(String fieldReference) {
@@ -548,7 +548,7 @@ public class ComparisonOperators {
* Creates new {@link Gt} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Gt}.
*/
public Gt greaterThan(AggregationExpression expression) {
@@ -560,7 +560,7 @@ public class ComparisonOperators {
* Creates new {@link Gt} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Gt}.
*/
public Gt greaterThanValue(Object value) {
@@ -589,7 +589,7 @@ public class ComparisonOperators {
* Creates new {@link Lt}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Lt}.
*/
public static Lt valueOf(String fieldReference) {
@@ -601,7 +601,7 @@ public class ComparisonOperators {
* Creates new {@link Lt}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Lt}.
*/
public static Lt valueOf(AggregationExpression expression) {
@@ -613,7 +613,7 @@ public class ComparisonOperators {
* Creates new {@link Lt} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Lt}.
*/
public Lt lessThan(String fieldReference) {
@@ -625,7 +625,7 @@ public class ComparisonOperators {
* Creates new {@link Lt} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Lt}.
*/
public Lt lessThan(AggregationExpression expression) {
@@ -637,7 +637,7 @@ public class ComparisonOperators {
* Creates new {@link Lt} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Lt}.
*/
public Lt lessThanValue(Object value) {
@@ -666,7 +666,7 @@ public class ComparisonOperators {
* Creates new {@link Gte}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Gte}.
*/
public static Gte valueOf(String fieldReference) {
@@ -678,7 +678,7 @@ public class ComparisonOperators {
* Creates new {@link Gte}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Gte}.
*/
public static Gte valueOf(AggregationExpression expression) {
@@ -690,7 +690,7 @@ public class ComparisonOperators {
* Creates new {@link Gte} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Gte}.
*/
public Gte greaterThanEqualTo(String fieldReference) {
@@ -702,7 +702,7 @@ public class ComparisonOperators {
* Creates new {@link Gte} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Gte}.
*/
public Gte greaterThanEqualTo(AggregationExpression expression) {
@@ -714,7 +714,7 @@ public class ComparisonOperators {
* Creates new {@link Gte} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Gte}.
*/
public Gte greaterThanEqualToValue(Object value) {
@@ -743,7 +743,7 @@ public class ComparisonOperators {
* Creates new {@link Lte}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Lte}.
*/
public static Lte valueOf(String fieldReference) {
@@ -755,7 +755,7 @@ public class ComparisonOperators {
* Creates new {@link Lte}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Lte}.
*/
public static Lte valueOf(AggregationExpression expression) {
@@ -767,7 +767,7 @@ public class ComparisonOperators {
* Creates new {@link Lte} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Lte}.
*/
public Lte lessThanEqualTo(String fieldReference) {
@@ -779,7 +779,7 @@ public class ComparisonOperators {
* Creates new {@link Lte} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Lte}.
*/
public Lte lessThanEqualTo(AggregationExpression expression) {
@@ -791,7 +791,7 @@ public class ComparisonOperators {
* Creates new {@link Lte} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Lte}.
*/
public Lte lessThanEqualToValue(Object value) {
@@ -820,7 +820,7 @@ public class ComparisonOperators {
* Creates new {@link Ne}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Ne}.
*/
public static Ne valueOf(String fieldReference) {
@@ -832,7 +832,7 @@ public class ComparisonOperators {
* Creates new {@link Ne}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Ne}.
*/
public static Ne valueOf(AggregationExpression expression) {
@@ -844,7 +844,7 @@ public class ComparisonOperators {
* Creates new {@link Ne} with all previously added arguments appending the given one.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Ne}.
*/
public Ne notEqualTo(String fieldReference) {
@@ -856,7 +856,7 @@ public class ComparisonOperators {
* Creates new {@link Ne} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Ne}.
*/
public Ne notEqualTo(AggregationExpression expression) {
@@ -868,12 +868,12 @@ public class ComparisonOperators {
* Creates new {@link Eq} with all previously added arguments appending the given one.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Ne}.
*/
public Ne notEqualToValue(Object value) {
Assert.notNull(value, "Value must not be null!");
return new Ne(append(value));
return new Ne(append(value, Expand.KEEP_SOURCE));
}
}
}

View File

@@ -43,7 +43,7 @@ public class ConditionalOperators {
* Take the field referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link ConditionalOperatorFactory}.
*/
public static ConditionalOperatorFactory when(String fieldReference) {
return new ConditionalOperatorFactory(fieldReference);
@@ -53,7 +53,7 @@ public class ConditionalOperators {
* Take the value resulting from the given {@literal expression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link ConditionalOperatorFactory}.
*/
public static ConditionalOperatorFactory when(AggregationExpression expression) {
return new ConditionalOperatorFactory(expression);
@@ -63,7 +63,7 @@ public class ConditionalOperators {
* Take the value resulting from the given {@literal criteriaDefinition}.
*
* @param criteriaDefinition must not be {@literal null}.
* @return
* @return new instance of {@link ConditionalOperatorFactory}.
*/
public static ConditionalOperatorFactory when(CriteriaDefinition criteriaDefinition) {
return new ConditionalOperatorFactory(criteriaDefinition);
@@ -75,7 +75,7 @@ public class ConditionalOperators {
* instances of undefined values or missing fields, returns the value of the replacement expression.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IfNull.ThenBuilder} to create {@link IfNull}.
*/
public static IfNull.ThenBuilder ifNull(String fieldReference) {
@@ -89,7 +89,7 @@ public class ConditionalOperators {
* instances of undefined values or missing fields, returns the value of the replacement expression.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IfNull.ThenBuilder} to create {@link IfNull}.
*/
public static IfNull.ThenBuilder ifNull(AggregationExpression expression) {
@@ -103,7 +103,7 @@ public class ConditionalOperators {
* out of the control flow.
*
* @param conditions must not be {@literal null}.
* @return
* @return new instance of {@link Switch}.
*/
public static Switch switchCases(CaseOperator... conditions) {
return Switch.switchCases(conditions);
@@ -115,7 +115,7 @@ public class ConditionalOperators {
* out of the control flow.
*
* @param conditions must not be {@literal null}.
* @return
* @return new instance of {@link Switch}.
*/
public static Switch switchCases(List<CaseOperator> conditions) {
return Switch.switchCases(conditions);
@@ -176,7 +176,7 @@ public class ConditionalOperators {
* return expressions.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link OtherwiseBuilder} to create {@link Cond}.
*/
public OtherwiseBuilder then(Object value) {
@@ -189,7 +189,7 @@ public class ConditionalOperators {
* return expressions.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link OtherwiseBuilder} to create {@link Cond}.
*/
public OtherwiseBuilder thenValueOf(AggregationExpression expression) {
@@ -202,7 +202,7 @@ public class ConditionalOperators {
* return expressions.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link OtherwiseBuilder} to create {@link Cond}.
*/
public OtherwiseBuilder thenValueOf(String fieldReference) {
@@ -233,9 +233,9 @@ public class ConditionalOperators {
* field references}, {@link AggregationExpression expressions}, values of simple MongoDB types or values that can be
* converted to a simple MongoDB type.
*
* @author Mark Paluch
* @see <a href=
* "https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/">https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/</a>
* @author Mark Paluch
*/
public static class IfNull implements AggregationExpression {
@@ -251,9 +251,9 @@ public class ConditionalOperators {
/**
* Creates new {@link IfNull}.
*
* @param fieldReference the field to check for a {@literal null} value, field reference must not be {@literal null}
* .
* @return
* @param fieldReference the field to check for a {@literal null} value, field reference must not be
* {@literal null}.
* @return never {@literal null}.
*/
public static ThenBuilder ifNull(String fieldReference) {
@@ -266,7 +266,7 @@ public class ConditionalOperators {
*
* @param expression the expression to check for a {@literal null} value, field reference must not be
* {@literal null}.
* @return
* @return never {@literal null}.
*/
public static ThenBuilder ifNull(AggregationExpression expression) {
@@ -338,19 +338,19 @@ public class ConditionalOperators {
* @param value the value to be used if the {@code $ifNull} condition evaluates {@literal true}. Can be a
* {@link Document}, a value that is supported by MongoDB or a value that can be converted to a MongoDB
* representation but must not be {@literal null}.
* @return
* @return new instance of {@link IfNull}.
*/
IfNull then(Object value);
/**
* @param fieldReference the field holding the replacement value, must not be {@literal null}.
* @return
* @return new instance of {@link IfNull}.
*/
IfNull thenValueOf(String fieldReference);
/**
* @param expression the expression yielding to the replacement value, must not be {@literal null}.
* @return
* @return new instance of {@link IfNull}.
*/
IfNull thenValueOf(AggregationExpression expression);
}
@@ -461,6 +461,12 @@ public class ConditionalOperators {
return new Switch(Collections.<String, Object> singletonMap("branches", new ArrayList<CaseOperator>(conditions)));
}
/**
* Set the default value.
*
* @param value must not be {@literal null}.
* @return new instance of {@link Switch}.
*/
public Switch defaultTo(Object value) {
return new Switch(append("default", value));
}
@@ -522,7 +528,7 @@ public class ConditionalOperators {
* Set the then {@literal value}.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link CaseOperator}.
*/
CaseOperator then(Object value);
}
@@ -536,10 +542,10 @@ public class ConditionalOperators {
* {@link AggregationExpression expressions}, values of simple MongoDB types or values that can be converted to a
* simple MongoDB type.
*
* @see <a href=
* "https://docs.mongodb.com/manual/reference/operator/aggregation/cond/">https://docs.mongodb.com/manual/reference/operator/aggregation/cond/</a>
* @author Mark Paluch
* @author Christoph Strobl
* @see <a href=
* "https://docs.mongodb.com/manual/reference/operator/aggregation/cond/">https://docs.mongodb.com/manual/reference/operator/aggregation/cond/</a>
*/
public static class Cond implements AggregationExpression {
@@ -664,7 +670,6 @@ public class ConditionalOperators {
}
clauses.add(new Document(key, args));
} else if (predicate instanceof Document) {
Document nested = (Document) predicate;
@@ -680,7 +685,6 @@ public class ConditionalOperators {
args.add(nested.get(s));
clauses.add(new Document(s, args));
}
} else if (!isKeyword(key)) {
List<Object> args = new ArrayList<Object>();

View File

@@ -34,9 +34,9 @@ public class CountOperation implements FieldsExposingAggregationOperation {
private final String fieldName;
/**
* Creates a new {@link CountOperation} given the {@link fieldName} field name.
* Creates a new {@link CountOperation} given the {@literal fieldName} field name.
*
* @param asFieldName must not be {@literal null} or empty.
* @param fieldName must not be {@literal null} or empty.
*/
public CountOperation(String fieldName) {
@@ -71,7 +71,7 @@ public class CountOperation implements FieldsExposingAggregationOperation {
* Returns the finally to be applied {@link CountOperation} with the given alias.
*
* @param fieldName must not be {@literal null} or empty.
* @return
* @return new instance of {@link CountOperation}.
*/
public CountOperation as(String fieldName) {
return new CountOperation(fieldName);

View File

@@ -30,7 +30,7 @@ public class DataTypeOperators {
* Return the BSON data type of the given {@literal field}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Type}.
*/
public static Type typeOf(String fieldReference) {
return Type.typeOf(fieldReference);
@@ -56,7 +56,7 @@ public class DataTypeOperators {
* Creates new {@link Type}.
*
* @param field must not be {@literal null}.
* @return
* @return new instance of {@link Type}.
*/
public static Type typeOf(String field) {

View File

@@ -37,7 +37,7 @@ public class DateOperators {
* Take the date referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link DateOperatorFactory}.
*/
public static DateOperatorFactory dateOf(String fieldReference) {
@@ -49,7 +49,7 @@ public class DateOperators {
* Take the date resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link DateOperatorFactory}.
*/
public static DateOperatorFactory dateOf(AggregationExpression expression) {
@@ -278,7 +278,7 @@ public class DateOperators {
* Creates new {@link AggregationExpression} that returns the day of the year for a date as a number between 1 and
* 366.
*
* @return
* @return new instance of {@link DayOfYear}.
*/
public DayOfYear dayOfYear() {
return applyTimezone(DayOfYear.dayOfYear(dateReference()), timezone);
@@ -288,7 +288,7 @@ public class DateOperators {
* Creates new {@link AggregationExpression} that returns the day of the month for a date as a number between 1 and
* 31.
*
* @return
* @return new instance of {@link DayOfMonth}.
*/
public DayOfMonth dayOfMonth() {
return applyTimezone(DayOfMonth.dayOfMonth(dateReference()), timezone);
@@ -298,7 +298,7 @@ public class DateOperators {
* Creates new {@link AggregationExpression} that returns the day of the week for a date as a number between 1
* (Sunday) and 7 (Saturday).
*
* @return
* @return new instance of {@link DayOfWeek}.
*/
public DayOfWeek dayOfWeek() {
return applyTimezone(DayOfWeek.dayOfWeek(dateReference()), timezone);
@@ -307,7 +307,7 @@ public class DateOperators {
/**
* Creates new {@link AggregationExpression} that returns the year portion of a date.
*
* @return
* @return new instance of {@link Year}.
*/
public Year year() {
return applyTimezone(Year.year(dateReference()), timezone);
@@ -316,7 +316,7 @@ public class DateOperators {
/**
* Creates new {@link AggregationExpression} that returns the month of a date as a number between 1 and 12.
*
* @return
* @return new instance of {@link Month}.
*/
public Month month() {
return applyTimezone(Month.month(dateReference()), timezone);
@@ -326,7 +326,7 @@ public class DateOperators {
* Creates new {@link AggregationExpression} that returns the week of the year for a date as a number between 0 and
* 53.
*
* @return
* @return new instance of {@link Week}.
*/
public Week week() {
return applyTimezone(Week.week(dateReference()), timezone);
@@ -335,7 +335,7 @@ public class DateOperators {
/**
* Creates new {@link AggregationExpression} that returns the hour portion of a date as a number between 0 and 23.
*
* @return
* @return new instance of {@link Hour}.
*/
public Hour hour() {
return applyTimezone(Hour.hour(dateReference()), timezone);
@@ -344,7 +344,7 @@ public class DateOperators {
/**
* Creates new {@link AggregationExpression} that returns the minute portion of a date as a number between 0 and 59.
*
* @return
* @return new instance of {@link Minute}.
*/
public Minute minute() {
return applyTimezone(Minute.minute(dateReference()), timezone);
@@ -354,7 +354,7 @@ public class DateOperators {
* Creates new {@link AggregationExpression} that returns the second portion of a date as a number between 0 and 59,
* but can be 60 to account for leap seconds.
*
* @return
* @return new instance of {@link Second}.
*/
public Second second() {
return applyTimezone(Second.second(dateReference()), timezone);
@@ -364,7 +364,7 @@ public class DateOperators {
* Creates new {@link AggregationExpression} that returns the millisecond portion of a date as an integer between 0
* and 999.
*
* @return
* @return new instance of {@link Millisecond}.
*/
public Millisecond millisecond() {
return applyTimezone(Millisecond.millisecond(dateReference()), timezone);
@@ -375,7 +375,7 @@ public class DateOperators {
* {@literal format}.
*
* @param format must not be {@literal null}.
* @return
* @return new instance of {@link DateToString}.
*/
public DateToString toString(String format) {
return applyTimezone(DateToString.dateToString(dateReference()).toString(format), timezone);
@@ -396,7 +396,7 @@ public class DateOperators {
* Creates new {@link AggregationExpression} that returns the weekday number in ISO 8601-2018 format, ranging from 1
* (for Monday) to 7 (for Sunday).
*
* @return
* @return new instance of {@link IsoDayOfWeek}.
*/
public IsoDayOfWeek isoDayOfWeek() {
return applyTimezone(IsoDayOfWeek.isoDayWeek(dateReference()), timezone);
@@ -406,7 +406,7 @@ public class DateOperators {
* Creates new {@link AggregationExpression} that returns the week number in ISO 8601-2018 format, ranging from 1 to
* 53.
*
* @return
* @return new instance of {@link IsoWeek}.
*/
public IsoWeek isoWeek() {
return applyTimezone(IsoWeek.isoWeek(dateReference()), timezone);
@@ -415,7 +415,7 @@ public class DateOperators {
/**
* Creates new {@link AggregationExpression} that returns the year number in ISO 8601-2018 format.
*
* @return
* @return new instance of {@link IsoWeekYear}.
*/
public IsoWeekYear isoWeekYear() {
return applyTimezone(IsoWeekYear.isoWeekYear(dateReference()), timezone);
@@ -642,7 +642,7 @@ public class DateOperators {
* Creates new {@link DayOfYear}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link DayOfYear}.
*/
public static DayOfYear dayOfYear(String fieldReference) {
@@ -654,7 +654,7 @@ public class DateOperators {
* Creates new {@link DayOfYear}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link DayOfYear}.
*/
public static DayOfYear dayOfYear(AggregationExpression expression) {
@@ -714,7 +714,7 @@ public class DateOperators {
* Creates new {@link DayOfMonth}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link DayOfMonth}.
*/
public static DayOfMonth dayOfMonth(String fieldReference) {
@@ -726,7 +726,7 @@ public class DateOperators {
* Creates new {@link DayOfMonth}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link DayOfMonth}.
*/
public static DayOfMonth dayOfMonth(AggregationExpression expression) {
@@ -786,7 +786,7 @@ public class DateOperators {
* Creates new {@link DayOfWeek}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link DayOfWeek}.
*/
public static DayOfWeek dayOfWeek(String fieldReference) {
@@ -798,7 +798,7 @@ public class DateOperators {
* Creates new {@link DayOfWeek}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link DayOfWeek}.
*/
public static DayOfWeek dayOfWeek(AggregationExpression expression) {
@@ -858,7 +858,7 @@ public class DateOperators {
* Creates new {@link Year}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Year}.
*/
public static Year yearOf(String fieldReference) {
@@ -870,7 +870,7 @@ public class DateOperators {
* Creates new {@link Year}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Year}.
*/
public static Year yearOf(AggregationExpression expression) {
@@ -930,7 +930,7 @@ public class DateOperators {
* Creates new {@link Month}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Month}.
*/
public static Month monthOf(String fieldReference) {
@@ -942,7 +942,7 @@ public class DateOperators {
* Creates new {@link Month}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Month}.
*/
public static Month monthOf(AggregationExpression expression) {
@@ -1002,7 +1002,7 @@ public class DateOperators {
* Creates new {@link Week}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Week}.
*/
public static Week weekOf(String fieldReference) {
@@ -1014,7 +1014,7 @@ public class DateOperators {
* Creates new {@link Week}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Week}.
*/
public static Week weekOf(AggregationExpression expression) {
@@ -1074,7 +1074,7 @@ public class DateOperators {
* Creates new {@link Hour}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Hour}.
*/
public static Hour hourOf(String fieldReference) {
@@ -1086,7 +1086,7 @@ public class DateOperators {
* Creates new {@link Hour}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Hour}.
*/
public static Hour hourOf(AggregationExpression expression) {
@@ -1146,7 +1146,7 @@ public class DateOperators {
* Creates new {@link Minute}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Minute}.
*/
public static Minute minuteOf(String fieldReference) {
@@ -1158,7 +1158,7 @@ public class DateOperators {
* Creates new {@link Minute}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Minute}.
*/
public static Minute minuteOf(AggregationExpression expression) {
@@ -1218,7 +1218,7 @@ public class DateOperators {
* Creates new {@link Second}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Second}.
*/
public static Second secondOf(String fieldReference) {
@@ -1230,7 +1230,7 @@ public class DateOperators {
* Creates new {@link Second}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Second}.
*/
public static Second secondOf(AggregationExpression expression) {
@@ -1290,7 +1290,7 @@ public class DateOperators {
* Creates new {@link Millisecond}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Millisecond}.
*/
public static Millisecond millisecondOf(String fieldReference) {
@@ -1302,7 +1302,7 @@ public class DateOperators {
* Creates new {@link Millisecond}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Millisecond}.
*/
public static Millisecond millisecondOf(AggregationExpression expression) {
@@ -1376,7 +1376,7 @@ public class DateOperators {
* Creates new {@link FormatBuilder} allowing to define the date format to apply.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link FormatBuilder} to crate {@link DateToString}.
*/
public static FormatBuilder dateOf(final String fieldReference) {
@@ -1388,7 +1388,7 @@ public class DateOperators {
* Creates new {@link FormatBuilder} allowing to define the date format to apply.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link FormatBuilder} to crate {@link DateToString}.
*/
public static FormatBuilder dateOf(final AggregationExpression expression) {
@@ -1540,7 +1540,7 @@ public class DateOperators {
* Creates new {@link IsoDayOfWeek}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IsoDayOfWeek}.
*/
public static IsoDayOfWeek isoDayOfWeek(String fieldReference) {
@@ -1552,7 +1552,7 @@ public class DateOperators {
* Creates new {@link IsoDayOfWeek}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IsoDayOfWeek}.
*/
public static IsoDayOfWeek isoDayOfWeek(AggregationExpression expression) {
@@ -1612,7 +1612,7 @@ public class DateOperators {
* Creates new {@link IsoWeek}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IsoWeek}.
*/
public static IsoWeek isoWeekOf(String fieldReference) {
@@ -1624,7 +1624,7 @@ public class DateOperators {
* Creates new {@link IsoWeek}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IsoWeek}.
*/
public static IsoWeek isoWeekOf(AggregationExpression expression) {
@@ -1684,7 +1684,7 @@ public class DateOperators {
* Creates new {@link IsoWeekYear}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IsoWeekYear}.
*/
public static IsoWeekYear isoWeekYearOf(String fieldReference) {
@@ -1696,7 +1696,7 @@ public class DateOperators {
* Creates new {@link Millisecond}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IsoWeekYear}.
*/
public static IsoWeekYear isoWeekYearOf(AggregationExpression expression) {
@@ -2378,6 +2378,7 @@ public class DateOperators {
@SuppressWarnings("unchecked")
private static <T extends TimezonedDateAggregationExpression> T applyTimezone(T instance, Timezone timezone) {
return !ObjectUtils.nullSafeEquals(Timezone.none(), timezone) && !instance.hasTimezone()
? (T) instance.withTimezone(timezone) : instance;
? (T) instance.withTimezone(timezone)
: instance;
}
}

View File

@@ -46,7 +46,7 @@ public final class ExposedFields implements Iterable<ExposedField> {
/**
* Returns an empty {@link ExposedFields} instance.
*
* @return
* @return never {@literal null}.
* @since 2.0
*/
public static ExposedFields empty() {
@@ -57,7 +57,7 @@ public final class ExposedFields implements Iterable<ExposedField> {
* Creates a new {@link ExposedFields} instance from the given {@link ExposedField}s.
*
* @param fields must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
public static ExposedFields from(ExposedField... fields) {
return from(Arrays.asList(fields));
@@ -67,7 +67,7 @@ public final class ExposedFields implements Iterable<ExposedField> {
* Creates a new {@link ExposedFields} instance from the given {@link ExposedField}s.
*
* @param fields must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
private static ExposedFields from(List<ExposedField> fields) {
@@ -84,7 +84,7 @@ public final class ExposedFields implements Iterable<ExposedField> {
* Creates synthetic {@link ExposedFields} from the given {@link Fields}.
*
* @param fields must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
public static ExposedFields synthetic(Fields fields) {
return createFields(fields, true);
@@ -94,7 +94,7 @@ public final class ExposedFields implements Iterable<ExposedField> {
* Creates non-synthetic {@link ExposedFields} from the given {@link Fields}.
*
* @param fields must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
public static ExposedFields nonSynthetic(Fields fields) {
return createFields(fields, false);
@@ -105,7 +105,7 @@ public final class ExposedFields implements Iterable<ExposedField> {
*
* @param fields must not be {@literal null}.
* @param synthetic
* @return
* @return never {@literal null}.
*/
private static ExposedFields createFields(Fields fields, boolean synthetic) {
@@ -135,7 +135,7 @@ public final class ExposedFields implements Iterable<ExposedField> {
* Creates a new {@link ExposedFields} adding the given {@link ExposedField}.
*
* @param field must not be {@literal null}.
* @return
* @return new instance of {@link ExposedFields}.
*/
public ExposedFields and(ExposedField field) {
@@ -151,8 +151,8 @@ public final class ExposedFields implements Iterable<ExposedField> {
/**
* Returns the field with the given name or {@literal null} if no field with the given name is available.
*
* @param name
* @return
* @param name must not be {@literal null}.
* @return can be {@literal null}.
*/
@Nullable
public ExposedField getField(String name) {

View File

@@ -146,7 +146,7 @@ public class GraphLookupOperation implements InheritsFieldsAggregationOperation
* Set the {@literal collectionName} to apply the {@code $graphLookup} to.
*
* @param collectionName must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
*/
StartWithBuilder from(String collectionName);
}
@@ -161,7 +161,7 @@ public class GraphLookupOperation implements InheritsFieldsAggregationOperation
* Set the startWith {@literal fieldReferences} to apply the {@code $graphLookup} to.
*
* @param fieldReferences must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
ConnectFromBuilder startWith(String... fieldReferences);
@@ -169,7 +169,7 @@ public class GraphLookupOperation implements InheritsFieldsAggregationOperation
* Set the startWith {@literal expressions} to apply the {@code $graphLookup} to.
*
* @param expressions must not be {@literal null}.
* @return
* @return never {@literal null}.
*/
ConnectFromBuilder startWith(AggregationExpression... expressions);
@@ -178,7 +178,7 @@ public class GraphLookupOperation implements InheritsFieldsAggregationOperation
* {@link AggregationExpression} to apply the {@code $graphLookup} to.
*
* @param expressions must not be {@literal null}.
* @return
* @return never {@literal null}.
* @throws IllegalArgumentException
*/
ConnectFromBuilder startWith(Object... expressions);
@@ -193,7 +193,7 @@ public class GraphLookupOperation implements InheritsFieldsAggregationOperation
* Set the connectFrom {@literal fieldName} to apply the {@code $graphLookup} to.
*
* @param fieldName must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
*/
ConnectToBuilder connectFrom(String fieldName);
}
@@ -207,7 +207,7 @@ public class GraphLookupOperation implements InheritsFieldsAggregationOperation
* Set the connectTo {@literal fieldName} to apply the {@code $graphLookup} to.
*
* @param fieldName must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
*/
GraphLookupOperationBuilder connectTo(String fieldName);
}
@@ -360,7 +360,7 @@ public class GraphLookupOperation implements InheritsFieldsAggregationOperation
* Optionally limit the number of recursions.
*
* @param numberOfRecursions must be greater or equal to zero.
* @return
* @return this.
*/
public GraphLookupOperationBuilder maxDepth(long numberOfRecursions) {
@@ -374,7 +374,7 @@ public class GraphLookupOperation implements InheritsFieldsAggregationOperation
* Optionally add a depth field {@literal fieldName} to each traversed document in the search path.
*
* @param fieldName must not be {@literal null} or empty.
* @return
* @return this.
*/
public GraphLookupOperationBuilder depthField(String fieldName) {

View File

@@ -89,7 +89,7 @@ public class LookupOperation implements FieldsExposingAggregationOperation, Inhe
/**
* Get a builder that allows creation of {@link LookupOperation}.
*
* @return
* @return never {@literal null}.
*/
public static FromBuilder newLookup() {
return new LookupOperationBuilder();
@@ -99,7 +99,7 @@ public class LookupOperation implements FieldsExposingAggregationOperation, Inhe
/**
* @param name the collection in the same database to perform the join with, must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
*/
LocalFieldBuilder from(String name);
}
@@ -109,7 +109,7 @@ public class LookupOperation implements FieldsExposingAggregationOperation, Inhe
/**
* @param name the field from the documents input to the {@code $lookup} stage, must not be {@literal null} or
* empty.
* @return
* @return never {@literal null}.
*/
ForeignFieldBuilder localField(String name);
}
@@ -118,7 +118,7 @@ public class LookupOperation implements FieldsExposingAggregationOperation, Inhe
/**
* @param name the field from the documents in the {@code from} collection, must not be {@literal null} or empty.
* @return
* @return never {@literal null}.
*/
AsBuilder foreignField(String name);
}
@@ -127,7 +127,7 @@ public class LookupOperation implements FieldsExposingAggregationOperation, Inhe
/**
* @param name the name of the new array field to add to the input documents, must not be {@literal null} or empty.
* @return
* @return new instance of {@link LookupOperation}.
*/
LookupOperation as(String name);
}

View File

@@ -31,7 +31,7 @@ import org.springframework.lang.Nullable;
* {@link AggregationOperationContext} implementation prefixing non-command keys on root level with the given prefix.
* Useful when mapping fields to domain specific types while having to prefix keys for query purpose.
* <p />
* Fields to be excluded from prefixing my be added to a {@literal blacklist}.
* Fields to be excluded from prefixing my be added to a {@literal denylist}.
*
* @author Christoph Strobl
* @author Mark Paluch
@@ -41,18 +41,18 @@ public class PrefixingDelegatingAggregationOperationContext implements Aggregati
private final AggregationOperationContext delegate;
private final String prefix;
private final Set<String> blacklist;
private final Set<String> denylist;
public PrefixingDelegatingAggregationOperationContext(AggregationOperationContext delegate, String prefix) {
this(delegate, prefix, Collections.emptySet());
}
public PrefixingDelegatingAggregationOperationContext(AggregationOperationContext delegate, String prefix,
Collection<String> blacklist) {
Collection<String> denylist) {
this.delegate = delegate;
this.prefix = prefix;
this.blacklist = new HashSet<>(blacklist);
this.denylist = new HashSet<>(denylist);
}
/*
@@ -121,7 +121,7 @@ public class PrefixingDelegatingAggregationOperationContext implements Aggregati
}
private String prefixKey(String key) {
return (key.startsWith("$") || isBlacklisted(key)) ? key : (prefix + "." + key);
return (key.startsWith("$") || isDenied(key)) ? key : (prefix + "." + key);
}
private Object prefixCollection(Collection<Object> sourceCollection) {
@@ -139,9 +139,9 @@ public class PrefixingDelegatingAggregationOperationContext implements Aggregati
return prefixed;
}
private boolean isBlacklisted(String key) {
private boolean isDenied(String key) {
if (blacklist.contains(key)) {
if (denylist.contains(key)) {
return true;
}
@@ -149,8 +149,8 @@ public class PrefixingDelegatingAggregationOperationContext implements Aggregati
return false;
}
for (String blacklisted : blacklist) {
if (key.startsWith(blacklisted + ".")) {
for (String denied : denylist) {
if (key.startsWith(denied + ".")) {
return true;
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.data.mongodb.core.aggregation;
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
import org.springframework.data.mongodb.core.convert.QueryMapper;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
/**
* A {@link TypeBasedAggregationOperationContext} with less restrictive field reference handling, suppressing
* {@link InvalidPersistentPropertyPath} exceptions when resolving mapped field names.
*
* @author Christoph Strobl
* @since 3.0
*/
public class RelaxedTypeBasedAggregationOperationContext extends TypeBasedAggregationOperationContext {
/**
* Creates a new {@link TypeBasedAggregationOperationContext} for the given type, {@link MappingContext} and
* {@link QueryMapper}.
*
* @param type must not be {@literal null}.
* @param mappingContext must not be {@literal null}.
* @param mapper must not be {@literal null}.
*/
public RelaxedTypeBasedAggregationOperationContext(Class<?> type,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext, QueryMapper mapper) {
super(type, mappingContext, mapper);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext#getReferenceFor(rg.springframework.data.mongodb.core.aggregation.Field)
*/
@Override
protected FieldReference getReferenceFor(Field field) {
try {
return super.getReferenceFor(field);
} catch (InvalidPersistentPropertyPath e) {
return new DirectFieldReference(new ExposedField(field, true));
}
}
}

View File

@@ -33,8 +33,7 @@ import org.springframework.util.Assert;
* @author Mark Paluch
* @author Christoph Strobl
* @since 1.10
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/">MongoDB Aggregation
* Framework: $replaceRoot</a>
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/">MongoDB Aggregation Framework: $replaceRoot</a>
*/
public class ReplaceRootOperation implements FieldsExposingAggregationOperation {
@@ -83,7 +82,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
*/
@Override
public Document toDocument(AggregationOperationContext context) {
return new Document("$replaceRoot", new Document("newRoot", getReplacement().toDocumentExpression(context)));
return new Document("$replaceRoot", new Document("newRoot", replacement.toDocumentExpression(context)));
}
/* (non-Javadoc)
@@ -94,16 +93,6 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
return ExposedFields.from();
}
/**
* Obtain the {@link Replacement}.
*
* @return never {@literal null}.
* @since 3.0
*/
protected Replacement getReplacement() {
return replacement;
}
/**
* Builder for {@link ReplaceRootOperation}.
*
@@ -166,7 +155,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
*
* @author Mark Paluch
*/
static class ReplaceRootDocumentOperation extends ReplaceRootOperation {
public static class ReplaceRootDocumentOperation extends ReplaceRootOperation {
private final static ReplacementDocument EMPTY = new ReplacementDocument();
private final ReplacementDocument current;
@@ -346,7 +335,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
/**
* Creates a {@link ReplacementDocument} given {@link ReplacementContributor}.
*
* @param contributor
* @param contributor must not be {@literal null}.
*/
protected ReplacementDocument(ReplacementContributor contributor) {
@@ -362,7 +351,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
* Creates a {@link ReplacementDocument} given a {@literal value}.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link ReplacementDocument}.
*/
public static ReplacementDocument valueOf(Object value) {
return new ReplacementDocument(new DocumentContributor(value));
@@ -372,7 +361,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
* Creates a {@link ReplacementDocument} given a single {@literal field} and {@link AggregationExpression}.
*
* @param aggregationExpression must not be {@literal null}.
* @return
* @return new instance of {@link ReplacementDocument}.
*/
public static ReplacementDocument forExpression(String field, AggregationExpression aggregationExpression) {
return new ReplacementDocument(new ExpressionFieldContributor(Fields.field(field), aggregationExpression));
@@ -382,7 +371,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
* Creates a {@link ReplacementDocument} given a single {@literal field} and {@literal value}.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link ReplacementDocument}.
*/
public static ReplacementDocument forSingleValue(String field, Object value) {
return new ReplacementDocument(new ValueFieldContributor(Fields.field(field), value));
@@ -438,7 +427,7 @@ public class ReplaceRootOperation implements FieldsExposingAggregationOperation
* {@link AggregationOperationContext}.
*
* @param context will never be {@literal null}.
* @return
* @return never {@literal null}.
*/
Document toDocument(AggregationOperationContext context);
}

View File

@@ -1,95 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.data.mongodb.core.aggregation;
import java.util.Collection;
import java.util.stream.Collectors;
import org.bson.Document;
import org.springframework.util.Assert;
/**
* Encapsulates the aggregation framework {@code $replaceRoot}-operation. <br />
* The operation replaces all existing fields including the {@code id} field with @{code $replaceWith}. This way it is
* possible to promote an embedded document to the top-level or specify a new document.
*
* @author Christoph Strobl
* @since 3.0
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/replaceWith/">MongoDB Aggregation
* Framework: $replaceWith</a>
*/
public class ReplaceWithOperation extends ReplaceRootOperation {
/**
* Creates new instance of {@link ReplaceWithOperation}.
*
* @param replacement must not be {@literal null}.
*/
public ReplaceWithOperation(Replacement replacement) {
super(replacement);
}
/**
* Creates new instance of {@link ReplaceWithOperation}.
*
* @param value must not be {@literal null}.
* @return new instance of {@link ReplaceWithOperation}.
*/
public static ReplaceWithOperation replaceWithValue(Object value) {
return new ReplaceWithOperation((ctx) -> value);
}
/**
* Creates new instance of {@link ReplaceWithOperation} treating a given {@link String} {@literal value} as a
* {@link Field field reference}.
*
* @param value must not be {@literal null}.
* @return
*/
public static ReplaceWithOperation replaceWithValueOf(Object value) {
Assert.notNull(value, "Value must not be null!");
return new ReplaceWithOperation((ctx) -> {
Object target = value instanceof String ? Fields.field((String) value) : value;
return computeValue(target, ctx);
});
}
private static Object computeValue(Object value, AggregationOperationContext context) {
if (value instanceof Field) {
return context.getReference((Field) value).toString();
}
if (value instanceof AggregationExpression) {
return ((AggregationExpression) value).toDocument(context);
}
if (value instanceof Collection) {
return ((Collection) value).stream().map(it -> computeValue(it, context)).collect(Collectors.toList());
}
return value;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public Document toDocument(AggregationOperationContext context) {
return context.getMappedObject(new Document("$replaceWith", getReplacement().toDocumentExpression(context)));
}
}

View File

@@ -1,250 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.data.mongodb.core.aggregation;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation;
import org.springframework.data.mongodb.core.aggregation.SetOperation.FieldAppender.ValueAppender;
import org.springframework.lang.Nullable;
/**
* Adds new fields to documents. {@code $set} outputs documents that contain all existing fields from the input
* documents and newly added fields.
*
* <pre class="code">
* SetOperation.set("totalHomework").toValue("A+").and().set("totalQuiz").toValue("B-")
* </pre>
*
* @author Christoph Strobl
* @since 3.0
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/set/">MongoDB Aggregation Framework:
* $set</a>
*/
public class SetOperation implements InheritsFieldsAggregationOperation {
private Map<Object, Object> valueMap;
private ExposedFields exposedFields = ExposedFields.empty();
/**
* Create new instance of {@link SetOperation} adding map keys as exposed fields.
*
* @param source must not be {@literal null}.
*/
private SetOperation(Map<Object, Object> source) {
this.valueMap = new LinkedHashMap<>(source);
for (Object key : source.keySet()) {
this.exposedFields = add(key);
}
}
/**
* Create new instance of {@link SetOperation}
*
* @param field must not be {@literal null}.
* @param value can be {@literal null}.
*/
public SetOperation(Object field, @Nullable Object value) {
this(Collections.singletonMap(field, value));
}
/**
* Define the {@link SetOperation} via {@link FieldAppender}.
*
* @return new instance of {@link FieldAppender}.
*/
public static FieldAppender builder() {
return new FieldAppender();
}
/**
* Concatenate another field to set.
*
* @param field must not be {@literal null}.
* @return new instance of {@link ValueAppender}.
*/
public static ValueAppender set(String field) {
return new FieldAppender().set(field);
}
/**
* Append the value for a specific field to the operation.
*
* @param field the target field to set.
* @param value the value to assign.
* @return new instance of {@link SetOperation}.
*/
public SetOperation set(Object field, Object value) {
LinkedHashMap<Object, Object> target = new LinkedHashMap<>(this.valueMap);
target.put(field, value);
return new SetOperation(target);
}
/**
* Concatenate additional fields to set.
*
* @return new instance of {@link FieldAppender}.
*/
public FieldAppender and() {
return new FieldAppender(this.valueMap);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public Document toDocument(AggregationOperationContext context) {
InheritingExposedFieldsAggregationOperationContext operationContext = new InheritingExposedFieldsAggregationOperationContext(
exposedFields, context);
if (valueMap.size() == 1) {
return context
.getMappedObject(new Document("$set", toSetEntry(valueMap.entrySet().iterator().next(), operationContext)));
}
Document $set = new Document();
valueMap.entrySet().stream().map(it -> toSetEntry(it, operationContext)).forEach($set::putAll);
return context.getMappedObject(new Document("$set", $set));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields()
*/
@Override
public ExposedFields getFields() {
return exposedFields;
}
private ExposedFields add(Object field) {
if (field instanceof Field) {
return exposedFields.and(new ExposedField((Field) field, true));
}
if (field instanceof String) {
return exposedFields.and(new ExposedField(Fields.field((String) field), true));
}
throw new IllegalArgumentException(String.format("Expected %s to be a field/property.", field));
}
private static Document toSetEntry(Entry<Object, Object> entry, AggregationOperationContext context) {
String field = entry.getKey() instanceof String ? context.getReference((String) entry.getKey()).getRaw()
: context.getReference((Field) entry.getKey()).getRaw();
Object value = computeValue(entry.getValue(), context);
return new Document(field, value);
}
private static Object computeValue(Object value, AggregationOperationContext context) {
if (value instanceof Field) {
return context.getReference((Field) value).toString();
}
if (value instanceof AggregationExpression) {
return ((AggregationExpression) value).toDocument(context);
}
if (value instanceof Collection) {
return ((Collection) value).stream().map(it -> computeValue(it, context)).collect(Collectors.toList());
}
return value;
}
/**
* @author Christoph Strobl
* @since 3.0
*/
public static class FieldAppender {
private final Map<Object, Object> valueMap;
private FieldAppender() {
this.valueMap = new LinkedHashMap<>();
}
private FieldAppender(Map<Object, Object> source) {
this.valueMap = new LinkedHashMap<>(source);
}
/**
* Define the field to set.
*
* @param field must not be {@literal null}.
* @return new instance of {@link ValueAppender}.
*/
public ValueAppender set(String field) {
return new ValueAppender() {
@Override
public SetOperation toValue(Object value) {
valueMap.put(field, value);
return FieldAppender.this.build();
}
@Override
public SetOperation toValueOf(Object value) {
valueMap.put(field, value instanceof String ? Fields.fields((String) value) : value);
return FieldAppender.this.build();
}
};
}
private SetOperation build() {
return new SetOperation(valueMap);
}
/**
* @author Christoph Strobl
* @since 3.0
*/
public interface ValueAppender {
/**
* Define the value to assign as is.
*
* @param value can be {@literal null}.
* @return new instance of {@link SetOperation}.
*/
SetOperation toValue(@Nullable Object value);
/**
* Define the value to assign. Plain {@link String} values are treated as {@link Field field references}.
*
* @param value must not be {@literal null}.
* @return new instance of {@link SetOperation}.
*/
SetOperation toValueOf(Object value);
}
}
}

View File

@@ -34,7 +34,7 @@ public class SetOperators {
* Take the array referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link SetOperatorFactory}.
*/
public static SetOperatorFactory arrayAsSet(String fieldReference) {
return new SetOperatorFactory(fieldReference);
@@ -44,7 +44,7 @@ public class SetOperators {
* Take the array resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetOperatorFactory}.
*/
public static SetOperatorFactory arrayAsSet(AggregationExpression expression) {
return new SetOperatorFactory(expression);
@@ -87,7 +87,7 @@ public class SetOperators {
* returns {@literal true} if they have the same distinct elements and {@literal false} otherwise.
*
* @param arrayReferences must not be {@literal null}.
* @return
* @return new instance of {@link SetEquals}.
*/
public SetEquals isEqualTo(String... arrayReferences) {
return createSetEquals().isEqualTo(arrayReferences);
@@ -98,7 +98,7 @@ public class SetOperators {
* returns {@literal true} if they have the same distinct elements and {@literal false} otherwise.
*
* @param expressions must not be {@literal null}.
* @return
* @return new instance of {@link SetEquals}.
*/
public SetEquals isEqualTo(AggregationExpression... expressions) {
return createSetEquals().isEqualTo(expressions);
@@ -113,7 +113,7 @@ public class SetOperators {
* arrays and returns an array that contains the elements that appear in every of those.
*
* @param arrayReferences must not be {@literal null}.
* @return
* @return new instance of {@link SetIntersection}.
*/
public SetIntersection intersects(String... arrayReferences) {
return createSetIntersection().intersects(arrayReferences);
@@ -124,7 +124,7 @@ public class SetOperators {
* arrays and returns an array that contains the elements that appear in every of those.
*
* @param expressions must not be {@literal null}.
* @return
* @return new instance of {@link SetIntersection}.
*/
public SetIntersection intersects(AggregationExpression... expressions) {
return createSetIntersection().intersects(expressions);
@@ -139,7 +139,7 @@ public class SetOperators {
* arrays and returns an array that contains the elements that appear in any of those.
*
* @param arrayReferences must not be {@literal null}.
* @return
* @return new instance of {@link SetUnion}.
*/
public SetUnion union(String... arrayReferences) {
return createSetUnion().union(arrayReferences);
@@ -150,7 +150,7 @@ public class SetOperators {
* arrays and returns an array that contains the elements that appear in any of those.
*
* @param expressions must not be {@literal null}.
* @return
* @return new instance of {@link SetUnion}.
*/
public SetUnion union(AggregationExpression... expressions) {
return createSetUnion().union(expressions);
@@ -165,7 +165,7 @@ public class SetOperators {
* containing the elements that do not exist in the given {@literal arrayReference}.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetDifference}.
*/
public SetDifference differenceTo(String arrayReference) {
return createSetDifference().differenceTo(arrayReference);
@@ -176,7 +176,7 @@ public class SetOperators {
* containing the elements that do not exist in the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetDifference}.
*/
public SetDifference differenceTo(AggregationExpression expression) {
return createSetDifference().differenceTo(expression);
@@ -191,7 +191,7 @@ public class SetOperators {
* {@literal true} if it is a subset of the given {@literal arrayReference}.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetIsSubset}.
*/
public SetIsSubset isSubsetOf(String arrayReference) {
return createSetIsSubset().isSubsetOf(arrayReference);
@@ -202,7 +202,7 @@ public class SetOperators {
* {@literal true} if it is a subset of the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetIsSubset}.
*/
public SetIsSubset isSubsetOf(AggregationExpression expression) {
return createSetIsSubset().isSubsetOf(expression);
@@ -216,7 +216,7 @@ public class SetOperators {
* Creates new {@link AggregationExpression} that takes array of the previously mentioned field and returns
* {@literal true} if any of the elements are {@literal true} and {@literal false} otherwise.
*
* @return
* @return new instance of {@link AnyElementTrue}.
*/
public AnyElementTrue anyElementTrue() {
return usesFieldRef() ? AnyElementTrue.arrayAsSet(fieldReference) : AnyElementTrue.arrayAsSet(expression);
@@ -226,7 +226,7 @@ public class SetOperators {
* Creates new {@link AggregationExpression} that tkes array of the previously mentioned field and returns
* {@literal true} if no elements is {@literal false}.
*
* @return
* @return new instance of {@link AllElementsTrue}.
*/
public AllElementsTrue allElementsTrue() {
return usesFieldRef() ? AllElementsTrue.arrayAsSet(fieldReference) : AllElementsTrue.arrayAsSet(expression);
@@ -257,7 +257,7 @@ public class SetOperators {
* Create new {@link SetEquals}.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetEquals}.
*/
public static SetEquals arrayAsSet(String arrayReference) {
@@ -269,7 +269,7 @@ public class SetOperators {
* Create new {@link SetEquals}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetEquals}.
*/
public static SetEquals arrayAsSet(AggregationExpression expression) {
@@ -281,7 +281,7 @@ public class SetOperators {
* Creates new {@link java.util.Set} with all previously added arguments appending the given one.
*
* @param arrayReferences must not be {@literal null}.
* @return
* @return new instance of {@link SetEquals}.
*/
public SetEquals isEqualTo(String... arrayReferences) {
@@ -293,7 +293,7 @@ public class SetOperators {
* Creates new {@link Sum} with all previously added arguments appending the given one.
*
* @param expressions must not be {@literal null}.
* @return
* @return new instance of {@link SetEquals}.
*/
public SetEquals isEqualTo(AggregationExpression... expressions) {
@@ -305,7 +305,7 @@ public class SetOperators {
* Creates new {@link Sum} with all previously added arguments appending the given one.
*
* @param array must not be {@literal null}.
* @return
* @return new instance of {@link SetEquals}.
*/
public SetEquals isEqualTo(Object[] array) {
@@ -334,7 +334,7 @@ public class SetOperators {
* Creates new {@link SetIntersection}
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetIntersection}.
*/
public static SetIntersection arrayAsSet(String arrayReference) {
@@ -346,7 +346,7 @@ public class SetOperators {
* Creates new {@link SetIntersection}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetIntersection}.
*/
public static SetIntersection arrayAsSet(AggregationExpression expression) {
@@ -358,7 +358,7 @@ public class SetOperators {
* Creates new {@link SetIntersection} with all previously added arguments appending the given one.
*
* @param arrayReferences must not be {@literal null}.
* @return
* @return new instance of {@link SetIntersection}.
*/
public SetIntersection intersects(String... arrayReferences) {
@@ -370,7 +370,7 @@ public class SetOperators {
* Creates new {@link SetIntersection} with all previously added arguments appending the given one.
*
* @param expressions must not be {@literal null}.
* @return
* @return new instance of {@link SetIntersection}.
*/
public SetIntersection intersects(AggregationExpression... expressions) {
@@ -399,7 +399,7 @@ public class SetOperators {
* Creates new {@link SetUnion}.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetUnion}.
*/
public static SetUnion arrayAsSet(String arrayReference) {
@@ -411,7 +411,7 @@ public class SetOperators {
* Creates new {@link SetUnion}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetUnion}.
*/
public static SetUnion arrayAsSet(AggregationExpression expression) {
@@ -423,7 +423,7 @@ public class SetOperators {
* Creates new {@link SetUnion} with all previously added arguments appending the given one.
*
* @param arrayReferences must not be {@literal null}.
* @return
* @return new instance of {@link SetUnion}.
*/
public SetUnion union(String... arrayReferences) {
@@ -435,7 +435,7 @@ public class SetOperators {
* Creates new {@link SetUnion} with all previously added arguments appending the given one.
*
* @param expressions must not be {@literal null}.
* @return
* @return new instance of {@link SetUnion}.
*/
public SetUnion union(AggregationExpression... expressions) {
@@ -464,7 +464,7 @@ public class SetOperators {
* Creates new {@link SetDifference}.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetDifference}.
*/
public static SetDifference arrayAsSet(String arrayReference) {
@@ -476,7 +476,7 @@ public class SetOperators {
* Creates new {@link SetDifference}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetDifference}.
*/
public static SetDifference arrayAsSet(AggregationExpression expression) {
@@ -488,7 +488,7 @@ public class SetOperators {
* Creates new {@link SetDifference} with all previously added arguments appending the given one.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetDifference}.
*/
public SetDifference differenceTo(String arrayReference) {
@@ -500,7 +500,7 @@ public class SetOperators {
* Creates new {@link SetDifference} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetDifference}.
*/
public SetDifference differenceTo(AggregationExpression expression) {
@@ -529,7 +529,7 @@ public class SetOperators {
* Creates new {@link SetIsSubset}.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetIsSubset}.
*/
public static SetIsSubset arrayAsSet(String arrayReference) {
@@ -541,7 +541,7 @@ public class SetOperators {
* Creates new {@link SetIsSubset}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetIsSubset}.
*/
public static SetIsSubset arrayAsSet(AggregationExpression expression) {
@@ -553,7 +553,7 @@ public class SetOperators {
* Creates new {@link SetIsSubset} with all previously added arguments appending the given one.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link SetIsSubset}.
*/
public SetIsSubset isSubsetOf(String arrayReference) {
@@ -565,7 +565,7 @@ public class SetOperators {
* Creates new {@link SetIsSubset} with all previously added arguments appending the given one.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SetIsSubset}.
*/
public SetIsSubset isSubsetOf(AggregationExpression expression) {
@@ -594,7 +594,7 @@ public class SetOperators {
* Creates new {@link AnyElementTrue}.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link AnyElementTrue}.
*/
public static AnyElementTrue arrayAsSet(String arrayReference) {
@@ -606,7 +606,7 @@ public class SetOperators {
* Creates new {@link AnyElementTrue}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link AnyElementTrue}.
*/
public static AnyElementTrue arrayAsSet(AggregationExpression expression) {
@@ -639,7 +639,7 @@ public class SetOperators {
* Creates new {@link AllElementsTrue}.
*
* @param arrayReference must not be {@literal null}.
* @return
* @return new instance of {@link AllElementsTrue}.
*/
public static AllElementsTrue arrayAsSet(String arrayReference) {
@@ -651,7 +651,7 @@ public class SetOperators {
* Creates new {@link AllElementsTrue}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link AllElementsTrue}.
*/
public static AllElementsTrue arrayAsSet(AggregationExpression expression) {

View File

@@ -35,7 +35,7 @@ public class StringOperators {
* Take the array referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StringOperatorFactory}.
*/
public static StringOperatorFactory valueOf(String fieldReference) {
return new StringOperatorFactory(fieldReference);
@@ -45,7 +45,7 @@ public class StringOperators {
* Take the array referenced by given {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StringOperatorFactory}.
*/
public static StringOperatorFactory valueOf(AggregationExpression fieldReference) {
return new StringOperatorFactory(fieldReference);
@@ -88,7 +88,7 @@ public class StringOperators {
* of the referenced field to it.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Concat}.
*/
public Concat concatValueOf(String fieldReference) {
@@ -101,7 +101,7 @@ public class StringOperators {
* of the given {@link AggregationExpression} to it.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Concat}.
*/
public Concat concatValueOf(AggregationExpression expression) {
@@ -114,7 +114,7 @@ public class StringOperators {
* {@literal value} to it.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Concat}.
*/
public Concat concat(String value) {
@@ -130,8 +130,8 @@ public class StringOperators {
* Creates new {@link AggregationExpression} that takes the associated string representation and returns a substring
* starting at a specified index position.
*
* @param start
* @return
* @param start start index number (including)
* @return new instance of {@link Substr}.
*/
public Substr substring(int start) {
return substring(start, -1);
@@ -141,9 +141,9 @@ public class StringOperators {
* Creates new {@link AggregationExpression} that takes the associated string representation and returns a substring
* starting at a specified index position including the specified number of characters.
*
* @param start
* @param nrOfChars
* @return
* @param start start index number (including)
* @param nrOfChars number of characters.
* @return new instance of {@link Substr}.
*/
public Substr substring(int start, int nrOfChars) {
return createSubstr().substring(start, nrOfChars);
@@ -156,7 +156,7 @@ public class StringOperators {
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and lowers it.
*
* @return
* @return new instance of {@link ToLower}.
*/
public ToLower toLower() {
return usesFieldRef() ? ToLower.lowerValueOf(fieldReference) : ToLower.lowerValueOf(expression);
@@ -165,7 +165,7 @@ public class StringOperators {
/**
* Creates new {@link AggregationExpression} that takes the associated string representation and uppers it.
*
* @return
* @return new instance of {@link ToUpper}.
*/
public ToUpper toUpper() {
return usesFieldRef() ? ToUpper.upperValueOf(fieldReference) : ToUpper.upperValueOf(expression);
@@ -176,7 +176,7 @@ public class StringOperators {
* case-insensitive comparison to the given {@literal value}.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link StrCaseCmp}.
*/
public StrCaseCmp strCaseCmp(String value) {
@@ -189,7 +189,7 @@ public class StringOperators {
* case-insensitive comparison to the referenced {@literal fieldReference}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StrCaseCmp}.
*/
public StrCaseCmp strCaseCmpValueOf(String fieldReference) {
@@ -202,7 +202,7 @@ public class StringOperators {
* case-insensitive comparison to the result of the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link StrCaseCmp}.
*/
public StrCaseCmp strCaseCmpValueOf(AggregationExpression expression) {
@@ -220,7 +220,7 @@ public class StringOperators {
* occurrence.
*
* @param substring must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfBytes}.
*/
public IndexOfBytes indexOf(String substring) {
@@ -234,7 +234,7 @@ public class StringOperators {
* index (zero-based) of the first occurrence.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfBytes}.
*/
public IndexOfBytes indexOf(Field fieldReference) {
@@ -248,7 +248,7 @@ public class StringOperators {
* byte index (zero-based) of the first occurrence.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfBytes}.
*/
public IndexOfBytes indexOf(AggregationExpression expression) {
@@ -266,7 +266,7 @@ public class StringOperators {
* first occurrence.
*
* @param substring must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfCP}.
*/
public IndexOfCP indexOfCP(String substring) {
@@ -280,7 +280,7 @@ public class StringOperators {
* point index (zero-based) of the first occurrence.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfCP}.
*/
public IndexOfCP indexOfCP(Field fieldReference) {
@@ -294,7 +294,7 @@ public class StringOperators {
* code point index (zero-based) of the first occurrence.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfCP}.
*/
public IndexOfCP indexOfCP(AggregationExpression expression) {
@@ -311,7 +311,7 @@ public class StringOperators {
* substrings based on the given delimiter.
*
* @param delimiter must not be {@literal null}.
* @return
* @return new instance of {@link Split}.
*/
public Split split(String delimiter) {
return createSplit().split(delimiter);
@@ -322,7 +322,7 @@ public class StringOperators {
* substrings based on the delimiter resulting from the referenced field..
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Split}.
*/
public Split split(Field fieldReference) {
return createSplit().split(fieldReference);
@@ -333,7 +333,7 @@ public class StringOperators {
* substrings based on a delimiter resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Split}.
*/
public Split split(AggregationExpression expression) {
return createSplit().split(expression);
@@ -347,7 +347,7 @@ public class StringOperators {
* Creates new {@link AggregationExpression} that returns the number of UTF-8 bytes in the associated string
* representation.
*
* @return
* @return new instance of {@link StrLenBytes}.
*/
public StrLenBytes length() {
return usesFieldRef() ? StrLenBytes.stringLengthOf(fieldReference) : StrLenBytes.stringLengthOf(expression);
@@ -357,7 +357,7 @@ public class StringOperators {
* Creates new {@link AggregationExpression} that returns the number of UTF-8 code points in the associated string
* representation.
*
* @return
* @return new instance of {@link StrLenCP}.
*/
public StrLenCP lengthCP() {
return usesFieldRef() ? StrLenCP.stringLengthOfCP(fieldReference) : StrLenCP.stringLengthOfCP(expression);
@@ -368,7 +368,7 @@ public class StringOperators {
* starting at a specified code point index position.
*
* @param codePointStart
* @return
* @return new instance of {@link SubstrCP}.
*/
public SubstrCP substringCP(int codePointStart) {
return substringCP(codePointStart, -1);
@@ -378,9 +378,9 @@ public class StringOperators {
* Creates new {@link AggregationExpression} that takes the associated string representation and returns a substring
* starting at a specified code point index position including the specified number of code points.
*
* @param codePointStart
* @param codePointStart start point (including).
* @param nrOfCodePoints
* @return
* @return new instance of {@link SubstrCP}.
*/
public SubstrCP substringCP(int codePointStart, int nrOfCodePoints) {
return createSubstrCP().substringCP(codePointStart, nrOfCodePoints);
@@ -541,7 +541,7 @@ public class StringOperators {
* Creates new {@link Concat}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Concat}.
*/
public static Concat valueOf(String fieldReference) {
@@ -553,7 +553,7 @@ public class StringOperators {
* Creates new {@link Concat}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Concat}.
*/
public static Concat valueOf(AggregationExpression expression) {
@@ -565,7 +565,7 @@ public class StringOperators {
* Creates new {@link Concat}.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link Concat}.
*/
public static Concat stringValue(String value) {
@@ -573,18 +573,36 @@ public class StringOperators {
return new Concat(Collections.singletonList(value));
}
/**
* Concat the value of the given field.
*
* @param fieldReference must not be {@literal null}.
* @return new instance of {@link Concat}.
*/
public Concat concatValueOf(String fieldReference) {
Assert.notNull(fieldReference, "FieldReference must not be null!");
return new Concat(append(Fields.field(fieldReference)));
}
/**
* Concat the value resulting from the given {@link AggregationExpression}.
*
* @param expression must not be {@literal null}.
* @return new instance of {@link Concat}.
*/
public Concat concatValueOf(AggregationExpression expression) {
Assert.notNull(expression, "Expression must not be null!");
return new Concat(append(expression));
}
/**
* Concat the given value.
*
* @param value must not be {@literal null}.
* @return new instance of {@link Concat}.
*/
public Concat concat(String value) {
return new Concat(append(value));
}
@@ -610,7 +628,7 @@ public class StringOperators {
* Creates new {@link Substr}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Substr}.
*/
public static Substr valueOf(String fieldReference) {
@@ -622,7 +640,7 @@ public class StringOperators {
* Creates new {@link Substr}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Substr}.
*/
public static Substr valueOf(AggregationExpression expression) {
@@ -630,10 +648,19 @@ public class StringOperators {
return new Substr(Collections.singletonList(expression));
}
/**
* @param start start index (including)
* @return new instance of {@link Substr}.
*/
public Substr substring(int start) {
return substring(start, -1);
}
/**
* @param start start index (including)
* @param nrOfChars
* @return new instance of {@link Substr}.
*/
public Substr substring(int start, int nrOfChars) {
return new Substr(append(Arrays.asList(start, nrOfChars)));
}
@@ -777,7 +804,7 @@ public class StringOperators {
* Creates new {@link StrCaseCmp}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link StrCaseCmp}.
*/
public static StrCaseCmp valueOf(AggregationExpression expression) {
@@ -789,7 +816,7 @@ public class StringOperators {
* Creates new {@link StrCaseCmp}.
*
* @param value must not be {@literal null}.
* @return
* @return new instance of {@link StrCaseCmp}.
*/
public static StrCaseCmp stringValue(String value) {
@@ -834,7 +861,7 @@ public class StringOperators {
* Start creating a new {@link IndexOfBytes}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link SubstringBuilder}.
*/
public static SubstringBuilder valueOf(String fieldReference) {
@@ -846,7 +873,7 @@ public class StringOperators {
* Start creating a new {@link IndexOfBytes}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SubstringBuilder}.
*/
public static SubstringBuilder valueOf(AggregationExpression expression) {
@@ -858,7 +885,7 @@ public class StringOperators {
* Optionally define the substring search start and end position.
*
* @param range must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfBytes}.
*/
public IndexOfBytes within(Range<Long> range) {
return new IndexOfBytes(append(AggregationUtils.toRangeValues(range)));
@@ -876,7 +903,7 @@ public class StringOperators {
* Creates a new {@link IndexOfBytes} given {@literal substring}.
*
* @param substring must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfBytes}.
*/
public IndexOfBytes indexOf(String substring) {
return new IndexOfBytes(Arrays.asList(stringExpression, substring));
@@ -886,7 +913,7 @@ public class StringOperators {
* Creates a new {@link IndexOfBytes} given {@link AggregationExpression} that resolves to the substring.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfBytes}.
*/
public IndexOfBytes indexOf(AggregationExpression expression) {
return new IndexOfBytes(Arrays.asList(stringExpression, expression));
@@ -896,7 +923,7 @@ public class StringOperators {
* Creates a new {@link IndexOfBytes} given {@link Field} that resolves to the substring.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfBytes}.
*/
public IndexOfBytes indexOf(Field fieldReference) {
return new IndexOfBytes(Arrays.asList(stringExpression, fieldReference));
@@ -924,7 +951,7 @@ public class StringOperators {
* Start creating a new {@link IndexOfCP}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfCP}.
*/
public static SubstringBuilder valueOf(String fieldReference) {
@@ -936,7 +963,7 @@ public class StringOperators {
* Start creating a new {@link IndexOfCP}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfCP}.
*/
public static SubstringBuilder valueOf(AggregationExpression expression) {
@@ -948,7 +975,7 @@ public class StringOperators {
* Optionally define the substring search start and end position.
*
* @param range must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfCP}.
*/
public IndexOfCP within(Range<Long> range) {
return new IndexOfCP(append(AggregationUtils.toRangeValues(range)));
@@ -966,7 +993,7 @@ public class StringOperators {
* Creates a new {@link IndexOfCP} given {@literal substring}.
*
* @param substring must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfCP}.
*/
public IndexOfCP indexOf(String substring) {
return new IndexOfCP(Arrays.asList(stringExpression, substring));
@@ -976,7 +1003,7 @@ public class StringOperators {
* Creates a new {@link IndexOfCP} given {@link AggregationExpression} that resolves to the substring.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link IndexOfCP}.
*/
public IndexOfCP indexOf(AggregationExpression expression) {
return new IndexOfCP(Arrays.asList(stringExpression, expression));
@@ -1014,7 +1041,7 @@ public class StringOperators {
* Start creating a new {@link Split}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Split}.
*/
public static Split valueOf(String fieldReference) {
@@ -1026,7 +1053,7 @@ public class StringOperators {
* Start creating a new {@link Split}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Split}.
*/
public static Split valueOf(AggregationExpression expression) {
@@ -1038,7 +1065,7 @@ public class StringOperators {
* Use given {@link String} as delimiter.
*
* @param delimiter must not be {@literal null}.
* @return
* @return new instance of {@link Split}.
*/
public Split split(String delimiter) {
@@ -1050,7 +1077,7 @@ public class StringOperators {
* Use value of referenced field as delimiter.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link Split}.
*/
public Split split(Field fieldReference) {
@@ -1062,7 +1089,7 @@ public class StringOperators {
* Use value resulting from {@link AggregationExpression} as delimiter.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link Split}.
*/
public Split split(AggregationExpression expression) {
@@ -1091,7 +1118,7 @@ public class StringOperators {
* Creates new {@link StrLenBytes}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StrLenBytes}.
*/
public static StrLenBytes stringLengthOf(String fieldReference) {
return new StrLenBytes(Fields.field(fieldReference));
@@ -1101,7 +1128,7 @@ public class StringOperators {
* Creates new {@link StrLenBytes}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link StrLenBytes}.
*/
public static StrLenBytes stringLengthOf(AggregationExpression expression) {
@@ -1130,7 +1157,7 @@ public class StringOperators {
* Creates new {@link StrLenCP}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link StrLenCP}.
*/
public static StrLenCP stringLengthOfCP(String fieldReference) {
return new StrLenCP(Fields.field(fieldReference));
@@ -1140,7 +1167,7 @@ public class StringOperators {
* Creates new {@link StrLenCP}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link StrLenCP}.
*/
public static StrLenCP stringLengthOfCP(AggregationExpression expression) {
@@ -1169,7 +1196,7 @@ public class StringOperators {
* Creates new {@link SubstrCP}.
*
* @param fieldReference must not be {@literal null}.
* @return
* @return new instance of {@link SubstrCP}.
*/
public static SubstrCP valueOf(String fieldReference) {
@@ -1181,7 +1208,7 @@ public class StringOperators {
* Creates new {@link SubstrCP}.
*
* @param expression must not be {@literal null}.
* @return
* @return new instance of {@link SubstrCP}.
*/
public static SubstrCP valueOf(AggregationExpression expression) {

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.List;
import org.bson.Document;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.aggregation.ExposedFields.DirectFieldReference;
@@ -127,7 +128,7 @@ public class TypeBasedAggregationOperationContext implements AggregationOperatio
return Fields.fields(fields.toArray(new String[0]));
}
protected FieldReference getReferenceFor(Field field) {
private FieldReference getReferenceFor(Field field) {
PersistentPropertyPath<MongoPersistentProperty> propertyPath = mappingContext
.getPersistentPropertyPath(field.getTarget(), type);

View File

@@ -1,144 +0,0 @@
/*
* Copyright 2019-2020 the original author or authors.
*
* 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
*
* https://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.
*/
package org.springframework.data.mongodb.core.aggregation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/**
* Removes fields from documents.
*
* @author Christoph Strobl
* @since 3.0
* @see <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/unset/">MongoDB Aggregation Framework:
* $unset</a>
*/
public class UnsetOperation implements InheritsFieldsAggregationOperation {
private final Collection<Object> fields;
/**
* Create new instance of {@link UnsetOperation}.
*
* @param fields must not be {@literal null}.
*/
public UnsetOperation(Collection<Object> fields) {
Assert.notNull(fields, "Fields must not be null!");
Assert.noNullElements(fields, "Fields must not contain null values.");
this.fields = fields;
}
/**
* Create new instance of {@link UnsetOperation}.
*
* @param fields must not be {@literal null}.
* @return new instance of {@link UnsetOperation}.
*/
public static UnsetOperation unset(String... fields) {
return new UnsetOperation(Arrays.asList(fields));
}
/**
* Also unset the given fields.
*
* @param fields must not be {@literal null}.
* @return new instance of {@link UnsetOperation}.
*/
public UnsetOperation and(String... fields) {
List<Object> target = new ArrayList<>(this.fields);
CollectionUtils.mergeArrayIntoCollection(fields, target);
return new UnsetOperation(target);
}
/**
* Also unset the given fields.
*
* @param fields must not be {@literal null}.
* @return new instance of {@link UnsetOperation}.
*/
public UnsetOperation and(Field... fields) {
List<Object> target = new ArrayList<>(this.fields);
CollectionUtils.mergeArrayIntoCollection(fields, target);
return new UnsetOperation(target);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation#getFields()
*/
@Override
public ExposedFields getFields() {
return ExposedFields.from();
}
Collection<String> removedFieldNames() {
List<String> fieldNames = new ArrayList<>(fields.size());
for (Object it : fields) {
if (it instanceof Field) {
fieldNames.add(((Field) it).getName());
} else {
fieldNames.add(it.toString());
}
}
return fieldNames;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperation#toDocument(org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
*/
@Override
public Document toDocument(AggregationOperationContext context) {
if (fields.size() == 1) {
return new Document("$unset", computeFieldName(fields.iterator().next(), context));
}
return new Document("$unset",
fields.stream().map(it -> computeFieldName(it, context)).collect(Collectors.toList()));
}
private Object computeFieldName(Object field, AggregationOperationContext context) {
if (field instanceof Field) {
return context.getReference((Field) field).getRaw();
}
if (field instanceof AggregationExpression) {
return ((AggregationExpression) field).toDocument(context);
}
if (field instanceof String) {
return context.getReference((String) field).getRaw();
}
return field;
}
}

View File

@@ -72,7 +72,7 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali
/**
* Registers {@link EntityInstantiators} to customize entity instantiation.
*
* @param instantiators
* @param instantiators can be {@literal null}. Uses default {@link EntityInstantiators} if so.
*/
public void setInstantiators(@Nullable EntityInstantiators instantiators) {
this.instantiators = instantiators == null ? new EntityInstantiators() : instantiators;

View File

@@ -46,7 +46,7 @@ public class CustomConversions extends MongoCustomConversions {
/**
* Creates a new {@link CustomConversions} instance registering the given converters.
*
* @param converters
* @param converters must not be {@literal null}.
*/
public CustomConversions(List<?> converters) {
super(converters);

View File

@@ -45,7 +45,7 @@ public interface DbRefResolver {
* @param property will never be {@literal null}.
* @param dbref the {@link DBRef} to resolve.
* @param callback will never be {@literal null}.
* @return
* @return can be {@literal null}.
*/
@Nullable
Object resolveDbRef(MongoPersistentProperty property, @Nullable DBRef dbref, DbRefResolverCallback callback,
@@ -58,7 +58,7 @@ public interface DbRefResolver {
* @param annotation will never be {@literal null}.
* @param entity will never be {@literal null}.
* @param id will never be {@literal null}.
* @return
* @return new instance of {@link DBRef}.
*/
default DBRef createDbRef(@Nullable org.springframework.data.mongodb.core.mapping.DBRef annotation,
MongoPersistentEntity<?> entity, Object id) {
@@ -74,7 +74,7 @@ public interface DbRefResolver {
* Actually loads the {@link DBRef} from the datasource.
*
* @param dbRef must not be {@literal null}.
* @return
* @return can be {@literal null}.
* @since 1.7
*/
@Nullable

View File

@@ -34,6 +34,7 @@ import org.aopalliance.intercept.MethodInvocation;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
@@ -44,6 +45,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.ClientSessionException;
import org.springframework.data.mongodb.LazyLoadingException;
import org.springframework.data.mongodb.MongoDatabaseUtils;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.lang.Nullable;
@@ -114,14 +116,16 @@ public class DefaultDbRefResolver implements DbRefResolver {
@Override
public Document fetch(DBRef dbRef) {
MongoCollection<Document> mongoCollection = getCollection(dbRef);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Fetching DBRef '{}' from {}.{}.", dbRef.getId(),
StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName() : mongoDbFactory.getDb().getName(),
StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName()
: mongoCollection.getNamespace().getDatabaseName(),
dbRef.getCollectionName());
}
StringUtils.hasText(dbRef.getDatabaseName());
return getCollection(dbRef).find(Filters.eq("_id", dbRef.getId())).first();
return mongoCollection.find(Filters.eq("_id", dbRef.getId())).first();
}
/*
@@ -152,15 +156,16 @@ public class DefaultDbRefResolver implements DbRefResolver {
}
DBRef databaseSource = refs.iterator().next();
MongoCollection<Document> mongoCollection = getCollection(databaseSource);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Bulk fetching DBRefs {} from {}.{}.", ids,
StringUtils.hasText(databaseSource.getDatabaseName()) ? databaseSource.getDatabaseName()
: mongoDbFactory.getDb().getName(),
: mongoCollection.getNamespace().getDatabaseName(),
databaseSource.getCollectionName());
}
List<Document> result = getCollection(databaseSource) //
List<Document> result = mongoCollection //
.find(new Document("_id", new Document("$in", ids))) //
.into(new ArrayList<>());
@@ -202,7 +207,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
proxyFactory.addInterface(propertyType);
proxyFactory.addAdvice(interceptor);
return handler.populateId(property, dbref, proxyFactory.getProxy());
return handler.populateId(property, dbref, proxyFactory.getProxy(LazyLoadingProxy.class.getClassLoader()));
}
/**
@@ -497,7 +502,7 @@ public class DefaultDbRefResolver implements DbRefResolver {
*/
protected MongoCollection<Document> getCollection(DBRef dbref) {
return (StringUtils.hasText(dbref.getDatabaseName()) ? mongoDbFactory.getDb(dbref.getDatabaseName())
: mongoDbFactory.getDb()).getCollection(dbref.getCollectionName(), Document.class);
return MongoDatabaseUtils.getDatabase(dbref.getDatabaseName(), mongoDbFactory)
.getCollection(dbref.getCollectionName(), Document.class);
}
}

View File

@@ -23,7 +23,6 @@ import java.util.function.UnaryOperator;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.convert.DefaultTypeMapper;
import org.springframework.data.convert.SimpleTypeInformationMapper;
@@ -42,9 +41,7 @@ import com.mongodb.DBObject;
/**
* Default implementation of {@link MongoTypeMapper} allowing configuration of the key to lookup and store type
* information in {@link Document}. The key defaults to {@link #DEFAULT_TYPE_KEY}. Actual type-to-{@link String}
* conversion and back is done in {@link #getTypeString(TypeInformation)} or {@link #getTypeInformation(String)}
* respectively.
* information in {@link Document}. The key defaults to {@link #DEFAULT_TYPE_KEY}.
*
* @author Oliver Gierke
* @author Thomas Darimont
@@ -111,7 +108,7 @@ public class DefaultMongoTypeMapper extends DefaultTypeMapper<Bson> implements M
* {@link TypeInformationMapper} to map type hints.
*
* @param typeKey name of the field to read and write type hints. Can be {@literal null} to disable type hints.
* @param mappers
* @param mappers must not be {@literal null}.
*/
public DefaultMongoTypeMapper(@Nullable String typeKey, List<? extends TypeInformationMapper> mappers) {
this(typeKey, new DocumentTypeAliasAccessor(typeKey), null, mappers);

View File

@@ -70,10 +70,10 @@ class DocumentAccessor {
/**
* Puts the given value into the backing {@link Document} based on the coordinates defined through the given
* {@link MongoPersistentProperty}. By default this will be the plain field name. But field names might also consist
* of path traversals so we might need to create intermediate {@link BasicDocument}s.
* of path traversals so we might need to create intermediate {@link Document}s.
*
* @param prop must not be {@literal null}.
* @param value
* @param value can be {@literal null}.
*/
public void put(MongoPersistentProperty prop, @Nullable Object value) {
@@ -106,7 +106,7 @@ class DocumentAccessor {
* a path expression in the field name metadata.
*
* @param property must not be {@literal null}.
* @return
* @return can be {@literal null}.
*/
@Nullable
public Object get(MongoPersistentProperty property) {
@@ -150,7 +150,7 @@ class DocumentAccessor {
* {@link MongoPersistentProperty}.
*
* @param property must not be {@literal null}.
* @return
* @return {@literal true} if no non {@literal null} value present.
*/
@SuppressWarnings("unchecked")
public boolean hasValue(MongoPersistentProperty property) {
@@ -203,7 +203,7 @@ class DocumentAccessor {
* Returns the given source object as map, i.e. {@link Document}s and maps as is or {@literal null} otherwise.
*
* @param source can be {@literal null}.
* @return
* @return can be {@literal null}.
*/
@Nullable
@SuppressWarnings("unchecked")

View File

@@ -91,7 +91,7 @@ abstract class GeoConverters {
/**
* Returns the geo converters to be registered.
*
* @return
* @return never {@literal null}.
*/
@SuppressWarnings("unchecked")
public static Collection<? extends Object> getConvertersToRegister() {
@@ -817,8 +817,8 @@ abstract class GeoConverters {
/**
* Converts a coordinate pairs nested in in {@link BasicDBList} into {@link GeoJsonPoint}s.
*
* @param listOfCoordinatePairs
* @return
* @param listOfCoordinatePairs must not be {@literal null}.
* @return never {@literal null}.
* @since 1.7
*/
@SuppressWarnings("unchecked")
@@ -841,8 +841,8 @@ abstract class GeoConverters {
/**
* Converts a coordinate pairs nested in in {@link BasicDBList} into {@link GeoJsonPolygon}.
*
* @param dbList
* @return
* @param dbList must not be {@literal null}.
* @return never {@literal null}.
* @since 1.7
*/
static GeoJsonPolygon toGeoJsonPolygon(List dbList) {

View File

@@ -90,8 +90,9 @@ import com.mongodb.DBRef;
* @author Christoph Strobl
* @author Jordi Llach
* @author Mark Paluch
* @author Heesu Jung
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, ValueResolver {
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware {
private static final String INCOMPATIBLE_TYPES = "Cannot convert %1$s of type %2$s into an instance of %3$s! Implement a custom Converter<%2$s, %3$s> and register it with the CustomConversions. Parent object was: %4$s";
private static final String INVALID_TYPE_TO_READ = "Expected to read Document %s into type %s but didn't find a PersistentEntity for the latter!";
@@ -131,7 +132,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
this.idMapper = new QueryMapper(this);
this.spELContext = new SpELContext(DocumentPropertyAccessor.INSTANCE);
this.dbRefProxyHandler = new DefaultDbRefProxyHandler(spELContext, mappingContext, MappingMongoConverter.this);
this.dbRefProxyHandler = new DefaultDbRefProxyHandler(spELContext, mappingContext,
MappingMongoConverter.this::getValueInternal);
}
/**
@@ -226,11 +228,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
@Nullable
@SuppressWarnings("unchecked")
private <S extends Object> S read(TypeInformation<S> type, @Nullable Bson bson, ObjectPath path) {
private <S extends Object> S read(TypeInformation<S> type, Bson bson, ObjectPath path) {
if (null == bson) {
return null;
}
Assert.notNull(bson, "Bson must not be null!");
TypeInformation<? extends S> typeToUse = typeMapper.readType(bson, type);
Class<? extends S> rawType = typeToUse.getType();
@@ -431,7 +431,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
SpELExpressionEvaluator evaluator) {
return new DefaultDbRefResolverCallback(documentAccessor.getDocument(), currentPath, evaluator,
MappingMongoConverter.this);
MappingMongoConverter.this::getValueInternal);
}
private void readAssociation(Association<MongoPersistentProperty> association, PersistentPropertyAccessor<?> accessor,
@@ -473,7 +473,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* Root entry method into write conversion. Adds a type discriminator to the {@link Document}. Shouldn't be called for
* nested conversions.
*
* @see org.springframework.data.mongodb.core.convert.MongoWriter#write(java.lang.Object, com.mongodb.Document)
* @see org.springframework.data.mongodb.core.convert.MongoWriter#write(java.lang.Object, java.lang.Object)
*/
public void write(Object obj, Bson bson) {
@@ -1047,7 +1047,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.convert.ValueResolver#getValueInternal(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, com.mongodb.Document, org.springframework.data.mapping.model.SpELExpressionEvaluator, java.lang.Object)
*/
@Override
@Nullable
public Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
ObjectPath path) {
return new MongoDbPropertyValueProvider(bson, evaluator, path).getPropertyValue(prop);
@@ -1261,9 +1261,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
if (conversions.isSimpleType(obj.getClass())) {
// Doesn't need conversion
return getPotentiallyConvertedSimpleWrite(obj,
typeInformation != null ? typeInformation.getType() : Object.class);
Class<?> conversionTargetType;
if (typeInformation != null && conversions.isSimpleType(typeInformation.getType())) {
conversionTargetType = typeInformation.getType();
} else {
conversionTargetType = Object.class;
}
return getPotentiallyConvertedSimpleWrite(obj, conversionTargetType);
}
if (obj instanceof List) {
@@ -1491,7 +1498,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
DbRefResolverCallback callback = new DefaultDbRefResolverCallback(accessor.getDocument(), path, evaluator,
MappingMongoConverter.this);
MappingMongoConverter.this::getValueInternal);
DBRef dbref = rawRefValue instanceof DBRef ? (DBRef) rawRefValue : null;
return (T) dbRefResolver.resolveDbRef(property, dbref, callback, dbRefProxyHandler);
@@ -1573,7 +1580,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
@Nullable
private <T> T readAndConvertDBRef(@Nullable DBRef dbref, TypeInformation<?> type, ObjectPath path,
final Class<?> rawType) {
@Nullable Class<?> rawType) {
List<T> result = bulkReadAndConvertDBRefs(Collections.singletonList(dbref), type, path, rawType);
return CollectionUtils.isEmpty(result) ? null : result.iterator().next();
@@ -1596,7 +1603,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
@SuppressWarnings("unchecked")
private <T> List<T> bulkReadAndConvertDBRefs(List<DBRef> dbrefs, TypeInformation<?> type, ObjectPath path,
final Class<?> rawType) {
@Nullable Class<?> rawType) {
if (CollectionUtils.isEmpty(dbrefs)) {
return Collections.emptyList();
@@ -1611,16 +1618,19 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
for (Document document : referencedRawDocuments) {
T target = null;
if (document != null) {
maybeEmitEvent(new AfterLoadEvent<>(document, (Class<T>) rawType, collectionName));
}
final T target = (T) read(type, document, path);
targeList.add(target);
maybeEmitEvent(
new AfterLoadEvent<>(document, (Class<T>) (rawType != null ? rawType : Object.class), collectionName));
target = (T) read(type, document, path);
}
if (target != null) {
maybeEmitEvent(new AfterConvertEvent<>(document, target, collectionName));
}
targeList.add(target);
}
return targeList;

View File

@@ -119,16 +119,16 @@ public interface MongoConverter
/**
* Converts the given raw id value into either {@link ObjectId} or {@link String}.
*
* @param id
* @param targetType
* @param id can be {@literal null}.
* @param targetType must not be {@literal null}.
* @return {@literal null} if source {@literal id} is already {@literal null}.
* @since 2.2
*/
@Nullable
default Object convertId(@Nullable Object id, Class<?> targetType) {
if (id == null) {
return null;
if (id == null || ClassUtils.isAssignableValue(targetType, id)) {
return id;
}
if (ClassUtils.isAssignable(ObjectId.class, targetType)) {

View File

@@ -110,7 +110,7 @@ abstract class MongoConverters {
INSTANCE;
public String convert(ObjectId id) {
return id.toString();
return id == null ? null : id.toString();
}
}
@@ -136,7 +136,7 @@ abstract class MongoConverters {
INSTANCE;
public BigInteger convert(ObjectId source) {
return new BigInteger(source.toString(), 16);
return source == null ? null : new BigInteger(source.toString(), 16);
}
}
@@ -149,7 +149,7 @@ abstract class MongoConverters {
INSTANCE;
public ObjectId convert(BigInteger source) {
return new ObjectId(source.toString(16));
return source == null ? null : new ObjectId(source.toString(16));
}
}
@@ -157,7 +157,7 @@ abstract class MongoConverters {
INSTANCE;
public String convert(BigDecimal source) {
return source.toString();
return source == null ? null : source.toString();
}
}
@@ -168,7 +168,7 @@ abstract class MongoConverters {
INSTANCE;
public Decimal128 convert(BigDecimal source) {
return new Decimal128(source);
return source == null ? null : new Decimal128(source);
}
}
@@ -195,7 +195,7 @@ abstract class MongoConverters {
INSTANCE;
public String convert(BigInteger source) {
return source.toString();
return source == null ? null : source.toString();
}
}
@@ -211,7 +211,7 @@ abstract class MongoConverters {
INSTANCE;
public String convert(URL source) {
return source.toString();
return source == null ? null : source.toString();
}
}
@@ -224,7 +224,7 @@ abstract class MongoConverters {
public URL convert(String source) {
try {
return new URL(source);
return source == null ? null : new URL(source);
} catch (MalformedURLException e) {
throw new ConversionFailedException(SOURCE, TARGET, source, e);
}
@@ -238,6 +238,11 @@ abstract class MongoConverters {
@Override
public String convert(Document source) {
if (source == null) {
return null;
}
return source.toJson();
}
}
@@ -253,7 +258,7 @@ abstract class MongoConverters {
@Override
public String convert(Term source) {
return source.getFormatted();
return source == null ? null : source.getFormatted();
}
}
@@ -268,7 +273,7 @@ abstract class MongoConverters {
@Override
public NamedMongoScript convert(Document source) {
if(source.isEmpty()) {
if (source == null) {
return null;
}
@@ -290,6 +295,10 @@ abstract class MongoConverters {
@Override
public Document convert(NamedMongoScript source) {
if (source == null) {
return new Document();
}
Document document = new Document();
document.put("_id", source.getName());
@@ -316,7 +325,7 @@ abstract class MongoConverters {
*/
@Override
public String convert(Currency source) {
return source.getCurrencyCode();
return source == null ? null : source.getCurrencyCode();
}
}
@@ -452,7 +461,7 @@ abstract class MongoConverters {
@Override
public AtomicLong convert(Long source) {
return new AtomicLong(source);
return source != null ? new AtomicLong(source) : null;
}
}
@@ -468,7 +477,7 @@ abstract class MongoConverters {
@Override
public AtomicInteger convert(Integer source) {
return new AtomicInteger(source);
return source != null ? new AtomicInteger(source) : null;
}
}
@@ -483,6 +492,7 @@ abstract class MongoConverters {
INSTANCE;
@Nullable
@Override
public byte[] convert(Binary source) {
return source.getData();
@@ -500,6 +510,7 @@ abstract class MongoConverters {
INSTANCE;
@Nullable
@Override
public Instant convert(BsonTimestamp source) {
return Instant.ofEpochSecond(source.getTime(), 0);

View File

@@ -24,7 +24,6 @@ import org.bson.BsonValue;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.domain.Example;
@@ -175,7 +174,7 @@ public class QueryMapper {
}
Document mappedSort = new Document();
for(Map.Entry<String,Object> entry : BsonUtils.asMap(sortObject).entrySet()) {
for (Map.Entry<String, Object> entry : BsonUtils.asMap(sortObject).entrySet()) {
Field field = createPropertyField(entity, entry.getKey(), mappingContext);
mappedSort.put(field.getMappedKey(), entry.getValue());
@@ -420,7 +419,7 @@ public class QueryMapper {
return false;
}
Class<? extends Object> type = value.getClass();
Class<?> type = value.getClass();
MongoPersistentProperty property = documentField.getProperty();
if (property.getActualType().isAssignableFrom(type)) {
@@ -444,7 +443,7 @@ public class QueryMapper {
protected Object convertSimpleOrDocument(Object source, @Nullable MongoPersistentEntity<?> entity) {
if (source instanceof Example) {
return exampleMapper.getMappedExample((Example) source, entity);
return exampleMapper.getMappedExample((Example<?>) source, entity);
}
if (source instanceof List) {
@@ -817,7 +816,7 @@ public class QueryMapper {
protected final String name;
/**
* Creates a new {@link DocumentField} without meta-information but the given name.
* Creates a new {@link Field} without meta-information but the given name.
*
* @param name must not be {@literal null} or empty.
*/
@@ -828,7 +827,7 @@ public class QueryMapper {
}
/**
* Returns a new {@link DocumentField} with the given name.
* Returns a new {@link Field} with the given name.
*
* @param name must not be {@literal null} or empty.
* @return
@@ -923,6 +922,8 @@ public class QueryMapper {
*/
protected static class MetadataBackedField extends Field {
private static final Pattern POSITIONAL_PARAMETER_PATTERN = Pattern.compile("\\.\\$(\\[.*?\\])?|\\.\\d+");
private static final Pattern DOT_POSITIONAL_PATTERN = Pattern.compile("\\.\\d+");
private static final String INVALID_ASSOCIATION_REFERENCE = "Invalid path reference %s! Associations can only be pointed to directly or via their id property!";
private final MongoPersistentEntity<?> entity;
@@ -964,7 +965,7 @@ public class QueryMapper {
this.entity = entity;
this.mappingContext = context;
this.path = getPath(name);
this.path = getPath(removePlaceholders(POSITIONAL_PARAMETER_PATTERN, name), property);
this.property = path == null ? property : path.getLeafProperty();
this.association = findAssociation();
}
@@ -1072,16 +1073,22 @@ public class QueryMapper {
}
/**
* Returns the {@link PersistentPropertyPath} for the given <code>pathExpression</code>.
* Returns the {@link PersistentPropertyPath} for the given {@code pathExpression}.
*
* @param pathExpression
* @return
*/
@Nullable
private PersistentPropertyPath<MongoPersistentProperty> getPath(String pathExpression) {
private PersistentPropertyPath<MongoPersistentProperty> getPath(String pathExpression,
@Nullable MongoPersistentProperty sourceProperty) {
String rawPath = pathExpression.replaceAll("\\.\\d+", "") //
.replaceAll(POSITIONAL_OPERATOR.pattern(), "");
String rawPath = removePlaceholders(POSITIONAL_OPERATOR,
removePlaceholders(DOT_POSITIONAL_PATTERN, pathExpression));
if (sourceProperty != null && sourceProperty.getOwner().equals(entity)) {
return mappingContext
.getPersistentPropertyPath(PropertyPath.from(sourceProperty.getName(), entity.getTypeInformation()));
}
PropertyPath path = forName(rawPath);
if (path == null || isPathToJavaLangClassProperty(path)) {
@@ -1158,7 +1165,7 @@ public class QueryMapper {
* @return
*/
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
return new PositionParameterRetainingPropertyKeyConverter(name);
return new PositionParameterRetainingPropertyKeyConverter(name, mappingContext);
}
/**
@@ -1169,7 +1176,15 @@ public class QueryMapper {
* @since 1.7
*/
protected Converter<MongoPersistentProperty, String> getAssociationConverter() {
return new AssociationConverter(getAssociation());
return new AssociationConverter(name, getAssociation());
}
protected MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
return mappingContext;
}
private static String removePlaceholders(Pattern pattern, String raw) {
return pattern.matcher(raw).replaceAll("");
}
/**
@@ -1180,8 +1195,9 @@ public class QueryMapper {
private final KeyMapper keyMapper;
public PositionParameterRetainingPropertyKeyConverter(String rawKey) {
this.keyMapper = new KeyMapper(rawKey);
public PositionParameterRetainingPropertyKeyConverter(String rawKey,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> ctx) {
this.keyMapper = new KeyMapper(rawKey, ctx);
}
/*
@@ -1223,7 +1239,8 @@ public class QueryMapper {
private final Iterator<String> iterator;
public KeyMapper(String key) {
public KeyMapper(String key,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
this.iterator = Arrays.asList(key.split("\\.")).iterator();
this.iterator.next();
@@ -1243,6 +1260,7 @@ public class QueryMapper {
while (inspect) {
String partial = iterator.next();
boolean isPositional = (isPositionalParameter(partial) && (property.isMap() || property.isCollectionLike()));
if (isPositional) {
@@ -1255,7 +1273,7 @@ public class QueryMapper {
return mappedName.toString();
}
private static boolean isPositionalParameter(String partial) {
static boolean isPositionalParameter(String partial) {
if ("$".equals(partial)) {
return true;
@@ -1283,6 +1301,7 @@ public class QueryMapper {
*/
protected static class AssociationConverter implements Converter<MongoPersistentProperty, String> {
private final String name;
private final MongoPersistentProperty property;
private boolean associationFound;
@@ -1291,10 +1310,11 @@ public class QueryMapper {
*
* @param association must not be {@literal null}.
*/
public AssociationConverter(Association<MongoPersistentProperty> association) {
public AssociationConverter(String name, Association<MongoPersistentProperty> association) {
Assert.notNull(association, "Association must not be null!");
this.property = association.getInverse();
this.name = name;
}
/*
@@ -1312,6 +1332,12 @@ public class QueryMapper {
associationFound = true;
}
if (associationFound) {
if (name.endsWith("$") && property.isCollectionLike()) {
return source.getFieldName() + ".$";
}
}
return source.getFieldName();
}
}

View File

@@ -272,6 +272,7 @@ public class UpdateMapper extends QueryMapper {
*
* @author Thomas Darimont
* @author Oliver Gierke
* @author Christoph Strobl
*/
private static class MetadataBackedUpdateField extends MetadataBackedField {
@@ -289,7 +290,7 @@ public class UpdateMapper extends QueryMapper {
public MetadataBackedUpdateField(MongoPersistentEntity<?> entity, String key,
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
super(key.replaceAll("\\.\\$(\\[.*\\])?", ""), entity, mappingContext);
super(key, entity, mappingContext);
this.key = key;
}
@@ -308,7 +309,7 @@ public class UpdateMapper extends QueryMapper {
*/
@Override
protected Converter<MongoPersistentProperty, String> getPropertyConverter() {
return new PositionParameterRetainingPropertyKeyConverter(key);
return new PositionParameterRetainingPropertyKeyConverter(key, getMappingContext());
}
/*
@@ -317,7 +318,7 @@ public class UpdateMapper extends QueryMapper {
*/
@Override
protected Converter<MongoPersistentProperty, String> getAssociationConverter() {
return new UpdateAssociationConverter(getAssociation(), key);
return new UpdateAssociationConverter(getMappingContext(), getAssociation(), key);
}
/**
@@ -334,10 +335,12 @@ public class UpdateMapper extends QueryMapper {
*
* @param association must not be {@literal null}.
*/
public UpdateAssociationConverter(Association<MongoPersistentProperty> association, String key) {
public UpdateAssociationConverter(
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext,
Association<MongoPersistentProperty> association, String key) {
super(association);
this.mapper = new KeyMapper(key);
super(key, association);
this.mapper = new KeyMapper(key, mappingContext);
}
/*

View File

@@ -19,12 +19,14 @@ import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.lang.Nullable;
/**
* Internal API to trigger the resolution of properties.
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
*/
interface ValueResolver {
@@ -35,9 +37,9 @@ interface ValueResolver {
* @param prop
* @param bson
* @param evaluator
* @param parent
* @param path
* @return
*/
Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator,
ObjectPath path);
@Nullable
Object getValueInternal(MongoPersistentProperty prop, Bson bson, SpELExpressionEvaluator evaluator, ObjectPath path);
}

View File

@@ -16,7 +16,7 @@
package org.springframework.data.mongodb.core.geo;
/**
* Interface definition for structures defined in GeoJSON ({@link https://geojson.org/}) format.
* Interface definition for structures defined in <a href="https://geojson.org/>GeoJSON</a> format.
*
* @author Christoph Strobl
* @since 1.7

View File

@@ -38,7 +38,7 @@ public class GeoJsonGeometryCollection implements GeoJson<Iterable<GeoJson<?>>>
/**
* Creates a new {@link GeoJsonGeometryCollection} for the given {@link GeoJson} instances.
*
* @param geometries
* @param geometries must not be {@literal null}.
*/
public GeoJsonGeometryCollection(List<GeoJson<?>> geometries) {

View File

@@ -58,7 +58,7 @@ public class Sphere implements Shape {
/**
* Creates a Sphere around the given center {@link Point} with the given radius.
*
* @param center
* @param center must not be {@literal null}.
* @param radius
*/
public Sphere(Point center, double radius) {
@@ -68,7 +68,7 @@ public class Sphere implements Shape {
/**
* Creates a Sphere from the given {@link Circle}.
*
* @param circle
* @param circle must not be {@literal null}.
*/
public Sphere(Circle circle) {
this(circle.getCenter(), circle.getRadius());
@@ -86,7 +86,7 @@ public class Sphere implements Shape {
/**
* Returns the radius of the {@link Circle}.
*
* @return
* @return never {@literal null}.
*/
public Distance getRadius() {
return radius;
@@ -136,7 +136,7 @@ public class Sphere implements Shape {
* Returns the {@link Shape} as a list of usually {@link Double} or {@link List}s of {@link Double}s. Wildcard bound
* to allow implementations to return a more concrete element type.
*
* @return
* @return never {@literal null}.
*/
public List<? extends Object> asList() {
return Arrays.asList(Arrays.asList(center.getX(), center.getY()), this.radius.getValue());
@@ -145,7 +145,7 @@ public class Sphere implements Shape {
/**
* Returns the command to be used to create the {@literal $within} criterion.
*
* @return
* @return never {@literal null}.
*/
public String getCommand() {
return COMMAND;

View File

@@ -74,7 +74,7 @@ public @interface CompoundIndex {
* }
* </pre>
*
* @return
* @return empty String by default.
*/
String def() default "";
@@ -82,13 +82,13 @@ public @interface CompoundIndex {
* It does not actually make sense to use that attribute as the direction has to be defined in the {@link #def()}
* attribute actually.
*
* @return
* @return {@link IndexDirection#ASCENDING} by default.
*/
@Deprecated
IndexDirection direction() default IndexDirection.ASCENDING;
/**
* @return
* @return {@literal false} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/core/index-unique/">https://docs.mongodb.org/manual/core/index-unique/</a>
*/
@@ -97,14 +97,14 @@ public @interface CompoundIndex {
/**
* If set to true index will skip over any document that is missing the indexed field.
*
* @return
* @return {@literal false} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/core/index-sparse/">https://docs.mongodb.org/manual/core/index-sparse/</a>
*/
boolean sparse() default false;
/**
* @return
* @return {@literal false} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping">https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping</a>
* @deprecated since 2.1. No longer supported by MongoDB as of server version 3.0.
@@ -148,7 +148,7 @@ public @interface CompoundIndex {
* db.hybrid.createIndex( { h1: 1, h2: 1 } , { name: "compound_index" } )
* </pre>
*
* @return
* @return empty String by default.
*/
String name() default "";
@@ -156,7 +156,7 @@ public @interface CompoundIndex {
* If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults
* to {@literal false}.
*
* @return
* @return {@literal false} by default
* @since 1.5
*/
boolean useGeneratedName() default false;
@@ -164,7 +164,7 @@ public @interface CompoundIndex {
/**
* If {@literal true} the index will be created in the background.
*
* @return
* @return {@literal false} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/core/indexes/#background-construction">https://docs.mongodb.org/manual/core/indexes/#background-construction</a>
*/

View File

@@ -72,7 +72,7 @@ public @interface GeoSpatialIndexed {
* </code>
* </pre>
*
* @return
* @return empty {@link String} by default.
*/
String name() default "";
@@ -80,7 +80,7 @@ public @interface GeoSpatialIndexed {
* If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults
* to {@literal false}.
*
* @return
* @return {@literal false} by default.
* @since 1.5
*/
boolean useGeneratedName() default false;
@@ -88,21 +88,21 @@ public @interface GeoSpatialIndexed {
/**
* Minimum value for indexed values.
*
* @return
* @return {@literal -180} by default.
*/
int min() default -180;
/**
* Maximum value for indexed values.
*
* @return
* @return {@literal +180} by default.
*/
int max() default 180;
/**
* Bits of precision for boundary calculations.
*
* @return
* @return {@literal 26} by default.
*/
int bits() default 26;
@@ -110,7 +110,7 @@ public @interface GeoSpatialIndexed {
* The type of the geospatial index. Default is {@link GeoSpatialIndexType#GEO_2D}
*
* @since 1.4
* @return
* @return {@link GeoSpatialIndexType#GEO_2D} by default.
*/
GeoSpatialIndexType type() default GeoSpatialIndexType.GEO_2D;
@@ -118,7 +118,7 @@ public @interface GeoSpatialIndexed {
* The bucket size for {@link GeoSpatialIndexType#GEO_HAYSTACK} indexes, in coordinate units.
*
* @since 1.4
* @return
* @return {@literal 1.0} by default.
*/
double bucketSize() default 1.0;
@@ -126,7 +126,7 @@ public @interface GeoSpatialIndexed {
* The name of the additional field to use for {@link GeoSpatialIndexType#GEO_HAYSTACK} indexes
*
* @since 1.4
* @return
* @return empty {@link String} by default.
*/
String additionalField() default "";
}

View File

@@ -59,7 +59,7 @@ public class GeospatialIndex implements IndexDefinition {
/**
* @param name must not be {@literal null} or empty.
* @return
* @return this.
*/
public GeospatialIndex named(String name) {
@@ -69,7 +69,7 @@ public class GeospatialIndex implements IndexDefinition {
/**
* @param min
* @return
* @return this.
*/
public GeospatialIndex withMin(int min) {
this.min = Integer.valueOf(min);
@@ -78,7 +78,7 @@ public class GeospatialIndex implements IndexDefinition {
/**
* @param max
* @return
* @return this.
*/
public GeospatialIndex withMax(int max) {
this.max = Integer.valueOf(max);
@@ -87,7 +87,7 @@ public class GeospatialIndex implements IndexDefinition {
/**
* @param bits
* @return
* @return this.
*/
public GeospatialIndex withBits(int bits) {
this.bits = Integer.valueOf(bits);
@@ -96,7 +96,7 @@ public class GeospatialIndex implements IndexDefinition {
/**
* @param type must not be {@literal null}.
* @return
* @return this.
*/
public GeospatialIndex typed(GeoSpatialIndexType type) {
@@ -108,7 +108,7 @@ public class GeospatialIndex implements IndexDefinition {
/**
* @param bucketSize
* @return
* @return this.
*/
public GeospatialIndex withBucketSize(double bucketSize) {
this.bucketSize = bucketSize;
@@ -116,8 +116,8 @@ public class GeospatialIndex implements IndexDefinition {
}
/**
* @param fieldName.
* @return
* @param fieldName
* @return this.
*/
public GeospatialIndex withAdditionalField(String fieldName) {
this.additionalField = fieldName;
@@ -128,7 +128,7 @@ public class GeospatialIndex implements IndexDefinition {
* Only index the documents in a collection that meet a specified {@link IndexFilter filter expression}.
*
* @param filter can be {@literal null}.
* @return
* @return this.
* @see <a href=
* "https://docs.mongodb.com/manual/core/index-partial/">https://docs.mongodb.com/manual/core/index-partial/</a>
* @since 1.10
@@ -146,7 +146,7 @@ public class GeospatialIndex implements IndexDefinition {
* index.
*
* @param collation can be {@literal null}.
* @return
* @return this.
* @since 2.0
*/
public GeospatialIndex collation(@Nullable Collation collation) {
@@ -155,6 +155,11 @@ public class GeospatialIndex implements IndexDefinition {
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexKeys()
*/
@Override
public Document getIndexKeys() {
Document document = new Document();
@@ -184,6 +189,11 @@ public class GeospatialIndex implements IndexDefinition {
return document;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexOptions()
*/
@Override
public Document getIndexOptions() {
Document document = new Document();

View File

@@ -40,7 +40,7 @@ public class HashedIndex implements IndexDefinition {
* Creates a new {@link HashedIndex} for the given field.
*
* @param field must not be {@literal null} nor empty.
* @return
* @return new instance of {@link HashedIndex}.
*/
public static HashedIndex hashed(String field) {
return new HashedIndex(field);

View File

@@ -73,7 +73,7 @@ public class Index implements IndexDefinition {
/**
* Reject all documents that contain a duplicate value for the indexed field.
*
* @return
* @return this.
* @see <a href=
* "https://docs.mongodb.org/manual/core/index-unique/">https://docs.mongodb.org/manual/core/index-unique/</a>
*/
@@ -85,7 +85,7 @@ public class Index implements IndexDefinition {
/**
* Skip over any document that is missing the indexed field.
*
* @return
* @return this.
* @see <a href=
* "https://docs.mongodb.org/manual/core/index-sparse/">https://docs.mongodb.org/manual/core/index-sparse/</a>
*/
@@ -97,7 +97,7 @@ public class Index implements IndexDefinition {
/**
* Build the index in background (non blocking).
*
* @return
* @return this.
* @since 1.5
*/
public Index background() {
@@ -110,7 +110,7 @@ public class Index implements IndexDefinition {
* Specifies TTL in seconds.
*
* @param value
* @return
* @return this.
* @since 1.5
*/
public Index expire(long value) {
@@ -135,8 +135,8 @@ public class Index implements IndexDefinition {
* Specifies TTL with given {@link TimeUnit}.
*
* @param value
* @param unit
* @return
* @param unit must not be {@literal null}.
* @return this.
* @since 1.5
*/
public Index expire(long value, TimeUnit unit) {
@@ -150,7 +150,7 @@ public class Index implements IndexDefinition {
* Only index the documents in a collection that meet a specified {@link IndexFilter filter expression}.
*
* @param filter can be {@literal null}.
* @return
* @return this.
* @see <a href=
* "https://docs.mongodb.com/manual/core/index-partial/">https://docs.mongodb.com/manual/core/index-partial/</a>
* @since 1.10
@@ -168,7 +168,7 @@ public class Index implements IndexDefinition {
* index.
*
* @param collation can be {@literal null}.
* @return
* @return this.
* @since 2.0
*/
public Index collation(@Nullable Collation collation) {
@@ -192,6 +192,10 @@ public class Index implements IndexDefinition {
return document;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.index.IndexDefinition#getIndexOptions()
*/
public Document getIndexOptions() {
Document document = new Document();

View File

@@ -24,7 +24,17 @@ import org.bson.Document;
*/
public interface IndexDefinition {
/**
* Get the {@link Document} containing properties covered by the index.
*
* @return never {@literal null}.
*/
Document getIndexKeys();
/**
* Get the index properties such as {@literal unique},...
*
* @return never {@literal null}.
*/
Document getIndexOptions();
}

View File

@@ -81,7 +81,7 @@ public final class IndexField {
* Creates a geo {@link IndexField} for the given key.
*
* @param key must not be {@literal null} or empty.
* @return
* @return new instance of {@link IndexField}.
*/
public static IndexField geo(String key) {
return new IndexField(key, null, Type.GEO);

View File

@@ -29,7 +29,7 @@ public interface IndexFilter {
/**
* Get the raw (unmapped) filter expression.
*
* @return
* @return never {@literal null}.
*/
Document getFilterObject();

View File

@@ -68,8 +68,8 @@ public class IndexInfo {
/**
* Creates new {@link IndexInfo} parsing required properties from the given {@literal sourceDocument}.
*
* @param sourceDocument
* @return
* @param sourceDocument never {@literal null}.
* @return new instance of {@link IndexInfo}.
* @since 1.10
*/
public static IndexInfo indexInfoOf(Document sourceDocument) {
@@ -135,7 +135,7 @@ public class IndexInfo {
}
/**
* @param sourceDocument
* @param sourceDocument never {@literal null}.
* @return the {@link String} representation of the partial filter {@link Document}.
* @since 2.1.11
*/

View File

@@ -52,7 +52,7 @@ public interface IndexResolver {
* Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s
* are created for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}.
*
* @param typeInformation
* @param typeInformation must not be {@literal null}.
* @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type.
*/
Iterable<? extends IndexDefinition> resolveIndexFor(TypeInformation<?> typeInformation);
@@ -61,7 +61,7 @@ public interface IndexResolver {
* Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s
* are created for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}.
*
* @param entityType
* @param entityType must not be {@literal null}.
* @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type.
* @see 2.2
*/

View File

@@ -39,25 +39,30 @@ public @interface Indexed {
/**
* If set to true reject all documents that contain a duplicate value for the indexed field.
*
* @return
* @return {@literal false} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/core/index-unique/">https://docs.mongodb.org/manual/core/index-unique/</a>
*/
boolean unique() default false;
/**
* The index sort direction.
*
* @return {@link IndexDirection#ASCENDING} by default.
*/
IndexDirection direction() default IndexDirection.ASCENDING;
/**
* If set to true index will skip over any document that is missing the indexed field.
*
* @return
* @return {@literal false} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/core/index-sparse/">https://docs.mongodb.org/manual/core/index-sparse/</a>
*/
boolean sparse() default false;
/**
* @return
* @return {@literal false} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping">https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping</a>
* @deprecated since 2.1. No longer supported by MongoDB as of server version 3.0.
@@ -105,7 +110,7 @@ public @interface Indexed {
* </code>
* </pre>
*
* @return
* @return empty String by default.
*/
String name() default "";
@@ -113,7 +118,7 @@ public @interface Indexed {
* If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults
* to {@literal false}.
*
* @return
* @return {@literal false} by default.
* @since 1.5
*/
boolean useGeneratedName() default false;
@@ -121,7 +126,7 @@ public @interface Indexed {
/**
* If {@literal true} the index will be created in the background.
*
* @return
* @return {@literal false} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/core/indexes/#background-construction">https://docs.mongodb.org/manual/core/indexes/#background-construction</a>
*/
@@ -130,7 +135,7 @@ public @interface Indexed {
/**
* Configures the number of seconds after which the collection should expire. Defaults to -1 for no expiry.
*
* @return
* @return {@literal -1} by default.
* @see <a href=
* "https://docs.mongodb.org/manual/tutorial/expire-data/">https://docs.mongodb.org/manual/tutorial/expire-data/</a>
*/

View File

@@ -77,7 +77,7 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
* {@link MongoDbFactory}.
*
* @param mappingContext must not be {@literal null}.
* @param mongoDbFactory must not be {@literal null}.
* @param indexOperationsProvider must not be {@literal null}.
* @param indexResolver must not be {@literal null}.
*/
public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext,

Some files were not shown because too many files have changed in this diff Show More