Currently I'm trying to, in an atomic way, since there will be multiple processes trying to access the same document, update or insert a document that contains multiple fields, one of which is a Map<Instant, Position>.
For this, I'm trying to use MongoTemplate, specifically the findAndModify() method which I've read provides the ACID properties I'm looking for. Given this, the query I implemented was the following:
slot.positions.forEach { position ->
mongoTemplate.findAndModify(
Query.query(Criteria.where("assetId").`is`(slot.assetId).and("startTime").`is`(slot.start)),
Update().set("positions.${position.key}", position.value).setOnInsert("updatedAt", Instant.now()),
FindAndModifyOptions.options().upsert(true),
SlotDocument::class.java,
)
}
The logic behind this was to try and upsert each position one at a time given that I do not know how to upsert the entire document all at once.
This attempt actually saves two positions successfully but then fails with the message:
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.Instant] for value [2023-08-28T09:57:30]
...
Caused by: java.time.format.DateTimeParseException: Text '2023-08-28T09:57:30' could not be parsed at index 19
This could be related to another issue I identified while debugging which was ever since I changed to the MongoTemplate, my MappgingMongoConverter stopped transforming .
into MIL
as specified by the code below
@Configuration
class MongoConfig {
/**
* This was my new attempt when changing to MongoTemplate
*/
@Bean
fun mongoTemplate(mongoDatabaseFactory: MongoDatabaseFactory, mappingMongoConverter: MappingMongoConverter): MongoTemplate {
mappingMongoConverter.setMapKeyDotReplacement("MIL")
return MongoTemplate(mongoDatabaseFactory, mappingMongoConverter)
}
/**
* Replaces dots in map keys that are to be stored in MongoDB
* This was the initial and successful attempt when using MongoRepository
*/
@Autowired
fun setMapKeyDotReplacement(mappingMongoConverter: MappingMongoConverter) {
mappingMongoConverter.setMapKeyDotReplacement("MIL")
}
}
So in the end, to summarise, I cannot:
- Upsert my slot document in order to, keeping the Atomic property, update the document and the content of its map field;
- Replace the
.
in the keys (Instant) of the map which is causing problems with the data structure in MongoDB