在弹性搜索和嵌套中传递和比较具有不同时区的日期时间值
passing and comparing datetime values with different timezones in elastic search and nest
我正在尝试在将参数与日期时间值(时区识别值)进行比较的查询中将日期时间值作为参数(时区识别值 'UTC')传递给日期时间值(时区识别值)' -05:00') 在弹性搜索文档和 returns 文档中。
问题:
1. 我在下面的代码中做得对吗?
2. 在将日期时间参数与文档日期时间值进行比较之前,ES 是否会处理日期时间参数不同时区的复杂性?
3. ES 是否会 return 具有原始日期时间时区值的文档?
4. 是否有任何文档揭示了弹性搜索实例时区处理的内部结构?
下面的代码 returns 值,但我不确定它是否达到了预期的 objective。
按照这个 link 但它仅限于一些基础知识
提前致谢。
ES源文件:
{
"took" : 12,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2700881,
"max_score" : 1.0,
"hits" : [
{
"_index" : "test_index",
"_type" : "doc",
"_id" : "R22224!!5333e7e4-9ee3-45f4-9dc3-2a8b8d8cdcf8",
"_score" : 1.0,
"_source" : {
"duration" : 14986283,
"group_id" : "com",
"var_time" : "2018-04-24T17:05:13.082-05:00",
"var_name" : "2",
}
}
]
}
}
public class RawDocument
{
[PropertyName("duration")]
public long Duration { get; set; }
[PropertyName("group_id")]
public string GroupId { get; set; }
[PropertyName("var_time")]
public DateTime Vartime { get; set; }
[PropertyName("var_name")]
public string Varname { get; set; }
}
static void Main(string[] args)
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool)
.DefaultMappingFor<RawDocument>(m => m
.IndexName(test_index)
.TypeName("doc"));
var client = new ElasticClient(settings);
//argument being passed into the query is maxExtractionTime datetime values. maxExtractionTime is in UTC
//maxExtractionTime is being compared to var_time datetime with timezone values
DateTime maxExtractionTime;
maxExtractionTime = DateTime oDate = DateTime.ParseExact("2019-02-08 16:10:40.000", "yyyy-MM-dd HH:mm.fff", System.Globalization.CultureInfo.InvariantCulture);
var searchResponse = client.Search<RawDocument>(s => s
.Size(5000)
.Scroll("2m")
.Query(q => q.DateRange(m => m.Field("var_time").GreaterThanOrEquals(maxExtractionTime.ToString("yyyy-MM-dd HH:mm:ss.fff")).TimeZone("+00:00")))
);
while (searchResponse.Documents.Any())
{
foreach (var document in searchResponse.Hits)
{
//do some business logic on the values
MessageBox.Show("document.Source.Duration", document.Source.Duration);
MessageBox.Show("document.Source.Vartime", document.Source.Vartime);
}
searchResponse = client.Scroll<RawDocument>("2m", searchResponse.ScrollId);
}
var clearScrollResponse = client.ClearScroll(c => c.ScrollId(searchResponse.ScrollId));
}
从您给 link 的文档中:
now is not affected by the time_zone parameter (dates must be stored as UTC)
从这个以及该页面上的其他示例,可以看出 time_zone
参数(或 C# 中的 .TimeZone(...)
)会影响查询的输入值。通过传递 +00:00
,您表示输入值不需要调整。
日期本身必须以 UTC 格式存储在文档中才能正确执行范围查询。您不应将 var_time
存储为 2018-04-24T17:05:13.082-05:00
,而应存储为 2018-04-24T17:10:13.082Z
。然后你可以查询它。
如有必要,存储两个字段,这样您就有一个用于查询,一个用于显示原始本地时间。
回答您的具体问题:
- Am I doing it correctly in my code below?
您的查询很好,但是 .TimeZone("+00:00")
没有必要,因为它不会调整参数。但是,您确实需要确保文档中的时间戳以 UTC 格式存储。
- Is ES going to handle the complexity of different timezone of the datetime argument before comparing it to the document datetime values ?
只是方便调整参数而已。它不会调整文档中的值。
- Is ES going to return the documents with the original datetime timezone values ?
文档应正常返回。更改查询中的时区不会影响它。
- Any documentation unraveling the internals of elastic search instance timezone handling ?
除了您 link 阅读的文档之外,我找不到太多内容。您应该尝试验证任何假设。
要添加到 ,当您输入的日期字符串有一个时区偏移量(或格式未指定一个时区偏移量,例如 2019-02-21
)时,发送时区很有帮助,但您希望 Elasticsearch在与存储在目标字段中的日期进行比较之前将其转换为另一个时区偏移量。
让我们看一些例子。
DateTimeKind.Utc
var client = new ElasticClient();
var maxExtractionTime = new DateTime(2019, 2, 8, 16, 10, 40, DateTimeKind.Utc);
var searchResponse = client.Search<RawDocument>(s => s
.Query(q => q
.DateRange(m => m
.Field(f => f.Vartime)
.GreaterThanOrEquals(maxExtractionTime)
)
)
);
序列化为
{
"query": {
"range": {
"var_time": {
"gte": "2019-02-08T16:10:40Z"
}
}
}
}
DateTimeKind.Local(我在澳大利亚)
var maxExtractionTime = new DateTime(2019, 2, 8, 16, 10, 40, DateTimeKind.Local);
序列化为
{
"query": {
"range": {
"var_time": {
"gte": "2019-02-08T16:10:40+10:00"
}
}
}
}
DateTimeKind.Unspecified
var maxExtractionTime = new DateTime(2019, 2, 8, 16, 10, 40, DateTimeKind.Unspecified);
序列化为
{
"query": {
"range": {
"var_time": {
"gte": "2019-02-08T16:10:40"
}
}
}
}
在前两种情况下,每个都包含 Elasticsearch 可以在比较日期时使用的时区偏移值。对于最后一个,不存在时区偏移,因此它将被解释为 UTC。在后一种情况下,您可能希望发送一个时区值以用于将输入转换为 UTC。
有些 history to DateTime
and DateTimeOffset
serialization within the client. The serialization in 6.x cannot be changed, except for DateTime
and DateTimeOffset
property types on your own POCOs, with a custom serializer hooked up. This limitation, if you will, is not often an issue however as most APIs within the client accept a DateMath
type 可以使用支持日期数学表达式的格式化日期字符串。对于 DateMath
,存在从 DateTime
和 string
的隐式转换,以及构建更复杂表达式的方法。
我正在尝试在将参数与日期时间值(时区识别值)进行比较的查询中将日期时间值作为参数(时区识别值 'UTC')传递给日期时间值(时区识别值)' -05:00') 在弹性搜索文档和 returns 文档中。
问题:
1. 我在下面的代码中做得对吗?
2. 在将日期时间参数与文档日期时间值进行比较之前,ES 是否会处理日期时间参数不同时区的复杂性?
3. ES 是否会 return 具有原始日期时间时区值的文档?
4. 是否有任何文档揭示了弹性搜索实例时区处理的内部结构?
下面的代码 returns 值,但我不确定它是否达到了预期的 objective。
按照这个 link 但它仅限于一些基础知识
提前致谢。
ES源文件:
{
"took" : 12,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 2700881,
"max_score" : 1.0,
"hits" : [
{
"_index" : "test_index",
"_type" : "doc",
"_id" : "R22224!!5333e7e4-9ee3-45f4-9dc3-2a8b8d8cdcf8",
"_score" : 1.0,
"_source" : {
"duration" : 14986283,
"group_id" : "com",
"var_time" : "2018-04-24T17:05:13.082-05:00",
"var_name" : "2",
}
}
]
}
}
public class RawDocument
{
[PropertyName("duration")]
public long Duration { get; set; }
[PropertyName("group_id")]
public string GroupId { get; set; }
[PropertyName("var_time")]
public DateTime Vartime { get; set; }
[PropertyName("var_name")]
public string Varname { get; set; }
}
static void Main(string[] args)
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool)
.DefaultMappingFor<RawDocument>(m => m
.IndexName(test_index)
.TypeName("doc"));
var client = new ElasticClient(settings);
//argument being passed into the query is maxExtractionTime datetime values. maxExtractionTime is in UTC
//maxExtractionTime is being compared to var_time datetime with timezone values
DateTime maxExtractionTime;
maxExtractionTime = DateTime oDate = DateTime.ParseExact("2019-02-08 16:10:40.000", "yyyy-MM-dd HH:mm.fff", System.Globalization.CultureInfo.InvariantCulture);
var searchResponse = client.Search<RawDocument>(s => s
.Size(5000)
.Scroll("2m")
.Query(q => q.DateRange(m => m.Field("var_time").GreaterThanOrEquals(maxExtractionTime.ToString("yyyy-MM-dd HH:mm:ss.fff")).TimeZone("+00:00")))
);
while (searchResponse.Documents.Any())
{
foreach (var document in searchResponse.Hits)
{
//do some business logic on the values
MessageBox.Show("document.Source.Duration", document.Source.Duration);
MessageBox.Show("document.Source.Vartime", document.Source.Vartime);
}
searchResponse = client.Scroll<RawDocument>("2m", searchResponse.ScrollId);
}
var clearScrollResponse = client.ClearScroll(c => c.ScrollId(searchResponse.ScrollId));
}
从您给 link 的文档中:
now is not affected by the time_zone parameter (dates must be stored as UTC)
从这个以及该页面上的其他示例,可以看出 time_zone
参数(或 C# 中的 .TimeZone(...)
)会影响查询的输入值。通过传递 +00:00
,您表示输入值不需要调整。
日期本身必须以 UTC 格式存储在文档中才能正确执行范围查询。您不应将 var_time
存储为 2018-04-24T17:05:13.082-05:00
,而应存储为 2018-04-24T17:10:13.082Z
。然后你可以查询它。
如有必要,存储两个字段,这样您就有一个用于查询,一个用于显示原始本地时间。
回答您的具体问题:
- Am I doing it correctly in my code below?
您的查询很好,但是 .TimeZone("+00:00")
没有必要,因为它不会调整参数。但是,您确实需要确保文档中的时间戳以 UTC 格式存储。
- Is ES going to handle the complexity of different timezone of the datetime argument before comparing it to the document datetime values ?
只是方便调整参数而已。它不会调整文档中的值。
- Is ES going to return the documents with the original datetime timezone values ?
文档应正常返回。更改查询中的时区不会影响它。
- Any documentation unraveling the internals of elastic search instance timezone handling ?
除了您 link 阅读的文档之外,我找不到太多内容。您应该尝试验证任何假设。
要添加到 2019-02-21
)时,发送时区很有帮助,但您希望 Elasticsearch在与存储在目标字段中的日期进行比较之前将其转换为另一个时区偏移量。
让我们看一些例子。
DateTimeKind.Utc
var client = new ElasticClient();
var maxExtractionTime = new DateTime(2019, 2, 8, 16, 10, 40, DateTimeKind.Utc);
var searchResponse = client.Search<RawDocument>(s => s
.Query(q => q
.DateRange(m => m
.Field(f => f.Vartime)
.GreaterThanOrEquals(maxExtractionTime)
)
)
);
序列化为
{
"query": {
"range": {
"var_time": {
"gte": "2019-02-08T16:10:40Z"
}
}
}
}
DateTimeKind.Local(我在澳大利亚)
var maxExtractionTime = new DateTime(2019, 2, 8, 16, 10, 40, DateTimeKind.Local);
序列化为
{
"query": {
"range": {
"var_time": {
"gte": "2019-02-08T16:10:40+10:00"
}
}
}
}
DateTimeKind.Unspecified
var maxExtractionTime = new DateTime(2019, 2, 8, 16, 10, 40, DateTimeKind.Unspecified);
序列化为
{
"query": {
"range": {
"var_time": {
"gte": "2019-02-08T16:10:40"
}
}
}
}
在前两种情况下,每个都包含 Elasticsearch 可以在比较日期时使用的时区偏移值。对于最后一个,不存在时区偏移,因此它将被解释为 UTC。在后一种情况下,您可能希望发送一个时区值以用于将输入转换为 UTC。
有些 history to DateTime
and DateTimeOffset
serialization within the client. The serialization in 6.x cannot be changed, except for DateTime
and DateTimeOffset
property types on your own POCOs, with a custom serializer hooked up. This limitation, if you will, is not often an issue however as most APIs within the client accept a DateMath
type 可以使用支持日期数学表达式的格式化日期字符串。对于 DateMath
,存在从 DateTime
和 string
的隐式转换,以及构建更复杂表达式的方法。