我试图在一个查询中传递一个日期时间值作为参数(在时区'UTC'中的时区无法识别值),该查询将参数与日期时间值(时区'-05:00'中的时区congnizant值)进行比较弹性搜索文档并返回文档。
问题: 1.我在下面的代码中正确地做了吗? 2.在将日期时间参数与文档日期时间值进行比较之前,ES是否会处理日期时间参数的不同时区的复杂性? 3. ES是否会使用原始日期时间值返回文档? 4.任何解释弹性搜索实例时区处理内部的文档? 下面的代码返回值,但我不确定它是否达到了预期的目标。 跟随这个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));
}
从文档中您链接到:
现在不受time_zone参数的影响(日期必须存储为UTC)
通过这个以及该页面上的其他示例,可以看出time_zone
参数(或C#中的.TimeZone(...)
)会影响查询的输入值。通过传递+00:00
,你说输入值不需要调整。
日期本身必须以UTC格式存储在文档中,以正确执行范围查询。你不应该将var_time
存储为2018-04-24T17:05:13.082-05:00
,而应该存储为2018-04-24T17:10:13.082Z
。然后你可以查询它。
如有必要,存储两个字段,因此您可以查询一个字段,一个字段显示原始本地时间。
回答您的具体问题:
- 我在下面的代码中正确地执行了吗?
你的查询没问题,但.TimeZone("+00:00")
is没有必要,因为它没有调整参数。但是,您需要确保文档中的时间戳以UTC格式存储。
- 在将datetime参数与文档日期时间值进行比较之前,ES是否会处理datetime参数的不同时区的复杂性?
调整参数只是一种方便。它不会调整文档中的值。
- ES是否会返回具有原始日期时间时区值的文档?
该文件应该正常返回。更改查询中的时区不会影响该区域。
- 任何解开弹性搜索实例时区处理内部的文档?
我找不到你所链接的文档之外的东西。您应该尝试验证任何假设。
要添加到Matt Johnson's answer,当您输入的日期字符串具有一个时区偏移量(或格式未指定一个例如2019-02-21
)时,发送时区会很有用,但您希望Elasticsearch将其转换为另一个时区偏移量,然后再与存储在中的日期进行比较目标领域。
我们来看一些例子。
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"
}
}
}
}
var maxExtractionTime = new DateTime(2019, 2, 8, 16, 10, 40, DateTimeKind.Local);
序列化为
{
"query": {
"range": {
"var_time": {
"gte": "2019-02-08T16:10:40+10:00"
}
}
}
}
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。 6.x中的序列化无法更改,除了您自己的POCO上的DateTime
和DateTimeOffset
属性类型,以及custom serializer hooked up。如果您愿意,此限制通常不是问题,因为客户端中的大多数API都接受DateMath
type,其中可以使用支持日期数学表达式的格式化日期字符串。使用DateMath
,有来自DateTime
和string
的隐式转换,以及构建更复杂表达式的方法。