Spring MongoDB Upsert Map Contents

34 Views Asked by At

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
0

There are 0 best solutions below