elasticsearch-net icon indicating copy to clipboard operation
elasticsearch-net copied to clipboard

Zero milliseconds are suppressed from DateTime values during serialization in DateRange queries

Open lekrus opened this issue 2 years ago • 2 comments

NEST/Elasticsearch.Net version: 7.13.2

Description of the problem including expected versus actual behavior: The issue is a side-effect of #3899 When DateTime values without milliseconds are serialized, milliseconds part is not included and that will result in wrong results for Lt, Gt queries.

Related ticket is https://github.com/elastic/elasticsearch/issues/62268

Steps to reproduce:

var dateWithoutMilliseconds = new DateTime(2022, 6, 11, 13, 54,  20, 0);
var serialized = Client.Serializer().SerializeToString(new SearchDescriptor<IDictionary>().AllIndices().Query(q => q
	.DateRange(dr=>dr
	.Field("test_field")
	.GreaterThan(dateWithoutMilliseconds)
)));
serialized.Should().Be("{\"query\":{\"range\":{\"test_field\":{\"gt\":\"2022-06-11T13:54:20.000\"}}}}");

Expected behavior It's expected the date serialized with milliseconds part: 2022-06-11T13:54:20.000 Currently that part is suppressed in ToMinThreeDecimalPlaces method that uses FFFFFF custom format that suppresses zeros and outputs: 2022-06-11T13:54:20

And then if we search for documents where test_field>"2022-06-11T13:54:20" Elasticsearch will not return documents with test_fields == "2022-06-11T13:54:20.125" (as I understood internally the value of 2022-06-11T13:54:20.999999 is used if milliseconds are omitted)

lekrus avatar Jun 11 '22 14:06 lekrus

This also affects v8 because System.Text.Json also omits the decimal places for such dates. We need to review if it's possible to support forcing these or if we can provide workarounds that are nice than dropping to low-level code.

var stream = new MemoryStream();

var dateWithoutMilliseconds = new DateTime(2022, 6, 11, 13, 54, 20, 0);

client.RequestResponseSerializer.Serialize(new SearchRequestDescriptor<Person>().Query(q => q
   .Range(dr => dr.DateRange(d => d
   .Field("test_field")
   .Gt(dateWithoutMilliseconds))
)), stream);

stream.Position = 0;
var reader = new StreamReader(stream);
var result = reader.ReadToEnd(); // {"query":{"range":{"test_field":{"gt":"2022-06-11T13:54:20"}}}}

stevejgordon avatar Apr 11 '23 15:04 stevejgordon

Well, my suggestion here is to improve serialization DateTime by using a custom converter first which isn't a problem, but it might be worth t introduce an Elastic specific type later where only a part of the date time can be set.

YohDeadfall avatar May 24 '23 10:05 YohDeadfall