Hi!
I use Nest 7.3 and a default serializer. And I have a problem with date serialization.
Suppose we have a model:
public class SearchEntity
{
[Date(Format = "date_time_no_millis")]
public DateTime Timestamp { get; set; }
}
I created index and a mapping of timestamp is OK.
Then I create an instance SearchEntity and try save it:
var entity = new SearchEntity { Timestamp = DateTime.Now };
client.Update(r => r
.DocAsUpsert()
.Doc(entity)
);
Here I get an error:
Type: mapper_parsing_exception Reason: "failed to parse field [timestamp] of type [date] in document with id '...'" CausedBy: "Type: illegal_argument_exception Reason: "failed to parse date field [2019-09-30T08:37:36.6356966+05:00] with format [date_time_no_millis]"
It doesn't matter, if I use date format date_time_no_millis, yyyy-MM-dd or any else, result the same.
What's wrong? How to set the field serialization format for DateTime property?
NEST client always serializes DateTime, DateTimeOffset POCO properties and their nullable counterparts, as ISO8601 strings. the Format property of the Date attribute does not influence how the DateTime or DateTimeOffset instance is serialized.
I've been thinking about ways in which Format could be supported, but there's a few things to consider:
For simple date patterns where there is a direct mapping of the pattern understood by Elasticsearch to a pattern that would be understood by .NET date formatting, I think this is the easiest case to handle.
For named date patterns understood by Elasticsearch, format patterns would need to be implemented in the client to serialize according to the named pattern formats.
POCOs that use attributes to specify Format would allow the creation of a custom DateFormatter when generating a formatter for the POCO through reflection, but Format can also be specified through fluent mapping. In this latter case, creating a custom DateFormatter is tricky because there may be no reflection metadata available to inform the format to use. Mapping could be fetched from an index but I can see several problems with this approach which I believe would make it untenable. There is the option of specifying the format with both fluent mapping and an attribute but this doesn't feel like a great solution.
One way to address formatting in the example provided for now would be to format the DateTime in the POCO to the desired format, and send the formatted value to Elasticsearch
public class SearchEntity
{
private DateTime _timestamp;
[Nest.Date(Name = "timestamp", Format = "date_time_no_millis")]
public string TimestampString
{
get => _timestamp.ToString("yyyy-MM-dd'T'HH:mm:ss");
private set => _timestamp = DateTime.ParseExact(value, "yyyy-MM-dd'T'HH:mm:ss", CultureInfo.InvariantCulture);
}
[Ignore]
public DateTime Timestamp
{
get => _timestamp;
set => _timestamp = value;
}
}
This would allow you to still work with DateTime in the POCO
var client = new ElasticClient(settings);
client.IndexDocument(new SearchEntity
{
Timestamp = new DateTime(2019,10,4,19,47,0)
});
yields
POST http://localhost:9200/index/_doc
{"timestamp":"2019-10-04T19:47:00"}
Ensure a SearchEntity can be deserialized from the output
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("{\"timestamp\":\"2019-10-04T19:47:00\"}")))
{
var doc = client.SourceSerializer.Deserialize<SearchEntity>(stream).Dump();
}
Apache, Apache Lucene, Apache Hadoop, Hadoop, HDFS and the yellow elephant
logo are trademarks of the
Apache Software Foundation
in the United States and/or other countries.