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.
Convert lineendings from CRLF to LF. Reduce validator implementations visibility to package. Extend Javadoc. Slight rewording in reference documentation.
Original pull request: #525.
Related pull request: #511.
Related ticket: DATACMNS-1835.
Remove ValidationAction/Level and ValidationOptions duplicates. Rename ValidatorDefinition to Validator and Validator to ValidationOptions.
Update and rename some of the tests. Also make sure to run the created validator document through the QueryMapper for value conversion and potential field mappings. Streamline Validator usage by providing plain Document and JsonSchema validator options next to the Criteria based one.
Finally update the reference documentation.
Original pull request: #525.
Related pull request: #511.
Related ticket: DATACMNS-1835.
Extended the CollectionOptions with a ValidationOptions property which
corresponds to the MongoDB createCollection() parameters. A validator
object can be defined using the Criteria API, or by writing a custom
provider.
Original pull request: #511.
Related pull request: #525.
Related ticket: DATACMNS-1835.
Add JSON schema to collection creation using reactive API. Refactor MongoJsonSchema to interface with default implementations for JsonSchemaObject and Document-based schemas. Make fields final and methods static where possible.
Add minItems/maxItems/additionalItems properties to ArrayJsonSchemaProperty. Add missing overrides to NullJsonSchemaProperty.
Slightly rename methods for item/property counts. Add generics, Javadoc, minor tweaks.
Original pull request: #524.
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.
We now support distinct queries via MongoTemplate to select distinct field values based on a collection and query.
List<String> distinctNames = template.findDistinct("name", Person.class, String.class);
List<String> distinctNames = template.query(Person.class).distinct("name").as(String.class).all();
Original pull request: #494.
Related pull request: #514.
We now make sure that we convert empty sources to the corresponding target type. This prevents entity instantiation from failing due to incorrect argument types when invoking the constructor.
Original pull request: #520.
In BasicMongoPersistentEntity.verify() we now properly call the super method to make sure the comparators that honor the @Field's order value are initialized properly.
Use native field names for NamedMongoScript query instead of relying on metadata-based mapping as NamedMongoScript is considered a simple top-level type. Migrate tests to AssertJ.
Related pull request: #513.
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.
We now use the driver native option for aggregate instead of a plain command execution. This is necessary as of MongoDB 3.6 the cursor option is required for aggregations changing the return and execution model.
Still we maintain the raw values of AggregationResult as we used to do before. However, relying on executeCommand to change aggregation behavior in custom code will no longer work.
Tested against MongoDB: 3.6.RC3, 3.4.9 and 3.2.6
Along the the way we opened up Aggregation itself to expose the AggregationOptions in use und deprecated the $pushAll option on Update since it has been removed in MongoDB 3.6.
Original pull request: #515.