marionmaiden
marionmaiden

Reputation: 3350

MongoDB truncating LocalDateTime nanosecs when MongoTemplate persists the data

I have a Spring Boot 2 project using MongoDB as database.

When I Instantiate an object containing a date as LocalDateTime by calling LocalDateTime.now(); I receive a datetime containing nanoseconds with more than 4 numerical places.

When I persist this data in mongoDB using mongotemplate.save, the value is saved containing 3 places for nanoseconds only (the rest is filled with zero). So, how can I accomplish the same precision when storing to DB? Or another option: how would I limit the precision when creating a LocalDateTime instance in java?

@Document("Entity")
public class Entity implements Serializable {

    @Id
    private String id;

    @Indexed(name = "created")
    private LocalDateTime created;

    public HistoryEntity(){
        // This gives me 2020-01-30T13:25:09.817182
        this.created = LocalDateTime.now();
    }
}

@Repository
public class DAO {

    @Autowired
    private MongoTemplate mongoTemplate;


    public void save(Entity e) {
        // When value is persisted, I get 2020-01-30T13:25:09.817 if I look into mongoDB instance or if I retrieve the same entity from DB in Java
        Entity saved = mongoTemplate.save(e);
    }
}

Upvotes: 2

Views: 3521

Answers (2)

Bruno 82
Bruno 82

Reputation: 519

If the LocalDateTime fields are only used for audit purposes (i.e. you don't need to query entities having a date/time field before/after a certain point in time) you can store date/time as a String, and deserialize the field back to your date/time object when retrieving the entity.

You can achieve this by registering custom converters in your mongo configuration. The following example is for Instant because I'm using Instant for audit fields rather than LocalDateTime, but you can easily adapt it for your need.

@Configuration
public class MongoCustomConfig {

  @Bean
  MongoCustomConversions mongoCustomConversions() {
    return new MongoCustomConversions(
        List.of(instantStringConverter()));
  }

  @Bean
  InstantStringConverter instantStringConverter() {
    return new InstantStringConverter();
  }

  private static class InstantStringConverter implements Converter<Instant, String> {

    @Override
    public String convert(Instant source) {
      return source.toString();
    }
  }
}

Upvotes: 0

marionmaiden
marionmaiden

Reputation: 3350

I think I found out the answer and probably there isn't much I can do other than truncate my LocalDateTime from java side (As I explained in my last comment and depicted below)

Clock millisecondClock = Clock.tick(Clock.systemDefaultZone(), Duration.ofNanos(1000000)); 
LocalDateTime d = LocalDateTime.now(millisecondClock);

I was reading this Baeldung's article https://www.baeldung.com/spring-data-mongodb-zoneddatetime when I faced the following statement (which answered my question):

... we're removing the nanoseconds information since the MongoDB Date type has a precision of milliseconds:

So that's it. Even if I want to work with a higher precision, seems that MongoDB can't handle it (at least for now)

Upvotes: 5

Related Questions