Remove DateFactory and split up tests.
Introduce dedicated Timezone abstraction and update existing factories to apply the timezone if appropriate. Update builders and align code style.
Original Pull Request: #539
Extend copyright license years. Slightly reword documentation. Use IntStream and insertAll to create test fixture.
Original pull request: #532.
Related pull request: #531.
We now use _id lookup for remove operations that query with limit or skip parameters. This allows more fine grained control over documents removed.
Original pull request: #532.
Related pull request: #531.
Allow reuse of builders instead of resetting state after MessagePropertiesBuilder.build(). Use Java streams where possible. Slightly reorder fields to match constructor argument order. Add generics to request builders and introduce typed builder(…) methods to retain builder generics. Add builder for TailableCursorRequest.
Introduce factory method on MessageListenerContainer for container creation. Change Subscription.await() to use CountDownLatch instead of polling to integrate better with ManagedBlocker.
Add protected constructors to options and builder classes. Add assertions where appropriate. Move task classes into top-level types. Extract methods. Typo fixes in reference docs.
Original pull request: #528.
As of MongoDB 3.6, Change Streams allow application to get notified about changes without having to tailing the oplog.
NOTE: Change Stream support is only available with replica sets or a sharded cluster.
Change Streams can be subscribed to with both the imperative and the reactive MongoDB java driver. It is highly recommended to use the reactive variant as it is less resource intensive. However if you do not feel comfortable using the reactive API for whatever reason, you can sill obtain the change events via a Messaging concept already common in the Spring ecosystem.
== Change Streams - Sync ==
Listening to a Change Stream using a Sync Driver is a long running, blocking task that needs to be delegated to a separate component.
In this case we need to create a MessageListenerContainer first which will be the main entry point for running the specific SubscriptionRequests.
Spring Data MongoDB already ships with a default implementation that operates upon MongoTemplate and is capable of creating and executing Tasks for a ChangeStreamRequest.
MessageListenerContainer container = MessageListenerContainer.create(template);
container.start();
MessageListener<ChangeStreamDocument<Document>, User> listener = System.out::println;
ChangeStreamRequestOptions options = new ChangeStreamRequestOptions("user", ChangeStreamOptions.empty());
Subscription subscription = container.register(new ChangeStreamRequest<>(listener, options), User.class);
== Change Streams - Reactive ==
Subscribing to Change Stream via the reactive API is clearly more straight forward. Still the building blocks like ChangeStreamOptions remain the same.
Aggregation filter = newAggregation(User.class, match(where("age").gte(38));
Flux<ChangeStreamEvent<User>> flux = reactiveTemplate.changeStream(filter), User.class, ChangeStreamOptions.empty());
== Tailable Cursors - Sync ==
This commit also adds support for tailable cursors using the synchronous driver to be used with capped collections:
MessageListenerContainer container = MessageListenerContainer.create(template);
container.start();
TailableCursorRequestOptions options = TailableCursorRequestOptions.builder()
.collection("user")
.filter(query(where("age").is(7)))
.build()
container.register(new TailableCursorRequest<>(messageListener, options, User.class));
Original pull request: #528.
We now can create a $jsonSchema that can be used as a validator when creating collections and as predicate for queries. Required fields and properties get mapped according to the @Field annotation on domain objects.
MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname")
.properties(string("firstname").possibleValues("luke", "han"),
object("address").properties(string("postCode").minLength(4).maxLength(5)))
.build();
resulting in the following schema:
{
"type": "object",
"required": [ "firstname", "lastname" ],
"properties": {
"firstname": {
"type": "string", "enum": [ "luke", "han" ],
},
"address": {
"type": "object",
"properties": {
"postCode": { "type": "string", "minLength": 4, "maxLength": 5 }
}
}
}
}
Query usage:
MongoJsonSchema schema = MongoJsonSchema.builder()
.required("address")
.property(object("address").properties(string("street").matching("^Apple.*"))).build();
List<Person> person = template.find(query(matchingDocumentStructure(schema)), Person.class));
Collection validation:
MongoJsonSchema schema = MongoJsonSchema.builder().required("firstname", "lastname")
.properties(string("firstname").possibleValues("luke", "han"),
object("address").properties(string("postCode").minLength(4).maxLength(5)))
.build();
template.createCollection(Person.class, CollectionOptions.empty()
.schema(schema)
.failOnValidationError());
Original pull request: #524.
Convert spaces to tabs. Reorder methods. Add tests, nullability annotations, author tags and slightly rearrange documentation. Migrate tests to AssertJ. Extend year range in license headers.
Original pull request: #519.
Refactor MongoConverter.mapValueToTargetType to imperative method instead of returning a function for easier consumption. Adapt return types in Javadoc to the actual return type. Remove undocumented type parameters. Add overload using reified entity and return type generics. Slight documentation tweaks.
Original pull request: #494.
Related pull request: #514.
Add rename and add methods to MongoOperations.
Map query, and use execute method to run errors through the execption translator. Add Javadoc and missing issue references.
Move to assertJ.
Also add fluent and reactive api counterpart and fix BsonValue to plain java Object / domain Type conversion.
Provide Kotlin extensions for operations added.
Original pull request: #494.
Related pull request: #514.
Introduce Aggregation.toPipeline(…) method to render the aggregation pipeline directly. Adapt code using aggregation pipelines. Consider allowDiskUse and batchSize cursor options. Move introduction versions to 2.1. Mention migration to cursor-based aggregation in reference docs.
Original pull request: #515.
Interfaces based projections handed to queries built using the FluentMongoOperations APIs now get projected as expected and also apply querying optimizations so that only fields needed in the projection are read in the first place.
Original pull request: #486.
Fix typos. Migrate to diamond syntax where applicable. Use Arrays.stream(…) instead of Arrays.asList(…).stream(). Mention percent sign as required char for URL encoding and reference RFC 3986 in documentation.
Original pull request: #477.
We now URL decode username & password before creating MongoCredentials. This allows usage of reserved characters in the credentials string.
Original pull request: #477.
Rename ICULocale to CollationLocale. Introduce interface for ComparisonLevel construction and let ICUComparisonLevel types implement that interface. Make value types immutable where possible. Provide static instances for default comparison level instances.
Replace collation conversion IndexConverters with Collation.from(…).toMongoCollation() converter. Introduce missing generic types. Replace Optional.get() with Optional.map(…).orElse(…).
Update reference documentation.
Original pull request: #459.
Fix documentation for namespace types. Remove unused ReflectiveDBCollectionInvoker. Simplify tests, align bean name to mongoClient. Remove injection of Mongo in favor of injecting MongoTemplate.
Remove throws declaration from AbstractMongoConfiguration.mongoClient(). MongoClient creation does not throw checked exceptions so throwing an Exception is no longer required. Replace Mongo by MongoClient in reference documentation.
Original pull request: #451.
Remove and replace usage of "mongo" by "mongoClient". This involves xsd schema, bean names, constructor and parameter types. This required some API changes as some server commands are no longer directly available through the api, but have to be invoked via runCommand.
Also remove references to outdated API using Credentials and an authentication DB instead of MongoCredentials for authentication.
Updated and removed (unused) tests; Altered documentation.
Original pull request: #451.
Field projections now expose their fields as synthetic simple fields. Projection aggregation stage redefines the available field set available for later aggregation stages entirely so projected fields are considered synthetic. A simple synthetic field has no target field which causes later aggregation stages to not pick up the underlying target but the exposed field name when rendering aggregation operations to Mongo documents.
The change is motivated by a bug where previously an aggregation consisting of projection of an aliased field and sort caused the sort projection stage to render with the original field name instead of the aliased field. The sort did not apply any sorting since projection redefines the available field set entirely and the original field is no longer accessible.
Original Pull Request: #433
We now support the $replaceRoot stage in aggregation pipelines. $replaceRoot can reference either a field, an aggregation expression or it can be used to compose a replacement document.
newAggregation(
replaceRoot().withDocument()
.andValue("value").as("field")
.and(MULTIPLY.of(field("total"), field("discounted")))
);
newAggregation(
replaceRoot("item")));
Original Pull Request: #422
We now support the following MongoDB 3.4 aggregation operators:
$indexOfBytes, $indexOfCP, $split, $strLenBytes, $strLenCP, $substrCP, $indexOfArray, $range, $reverseArray, $reduce, $zip, $in, $isoDayOfWeek, $isoWeek, $isoWeekYear, $switch and $type.
Original pull request: #423.
Add missing transformations for ConstructorReference, OperatorNot, OpNE, OpEQ, OpGT, OpGE, OpLT, OpLE, OperatorPower, OpOr and OpAnd. This allows usage of logical operators &, || and ! as part of the expression, while ConstructorReference allows instantiating eg. arrays via an expression `new int[]{4,5,6}`. This can be useful eg. comparing arrays using $setEquals.
More complex aggregation operators like $filter can be created by defining the variable references as string inside the expression like filter(a, 'num', '$$num' > 10).
Commands like $let requires usage of InlineMap to pass in required arguments like eg. let({low:1, high:'$$low'}, gt('$$low', '$$high')).
Original Pull Request: #410
We new support $filter in aggregation pipeline.
Aggregation.newAggregation(Sales.class,
Aggregation.project()
.and(filter("items").as("item").by(GTE.of(field("item.price"), 100)))
.as("items"))
Original pull request: #412.
Adopt type hint assertion for existing _class field checks. Simplify test code to use Collections.singletonList instead of Arrays.asList. Replace BasicDBList with List in JavaDoc. Use type inference for DocumentTestUtils.getAsDBList to avoid casts in test code. Extend documentation.
Original pull request: #411.
Favor usage of List over BasicDBList.
Rename ProjectionOperation.transform to applyCondition.
Add missing author and since tags, remove trailing white spaces and fix reference documentation headline clash.
Original Pull Request: #385
We now support $cond and $ifNull operators for projection and grouping operations. ConditionalOperator and IfNullOperators are AggregationExpressions that can be applied to transform or generate values during aggregation.
TypedAggregation<InventoryItem> agg = newAggregation(InventoryItem.class,
project().and("discount")
.transform(ConditionalOperator.newBuilder().when(Criteria.where("qty").gte(250))
.then(30)
.otherwise(20))
.and(ifNull("description", "Unspecified")).as("description")
);
corresponds to
{ "$project": { "discount": { "$cond": { "if": { "$gte": [ "$qty", 250 ] },
"then": 30, "else": 20 } },
"description": { "$ifNull": [ "$description", "Unspecified"] }
}
}
Original Pull Request: #385
We added methods to set values for $caseSensitive and $diacriticSensitive when using TextCriteria. Both operators are optional and will not be used until explicitly set.
// { "$text" : { "$search" : "coffee" , "$caseSensitive" : true } }
TextCriteria.forDefaultLanguage().matching("coffee").caseSensitive(true);
// { "$text" : { "$search" : "coffee" , "$diacriticSensitive" : true } }
TextCriteria.forDefaultLanguage().matching("coffee").diacriticSensitive(true);
Original pull request: #375.
Moved newly introduced types into order. Added missing @since tag and additional test.
Updated reference documentation for update operators and added $slice operator to "what’s new" section.
Original Pull Request: #374