使用 NEST api 进行弹性搜索的日期范围搜索返回不适当的结果
Date Range search using NEST api for elastic search returning inappropriate results
我正在尝试使用 NEST 在弹性搜索中使用日期范围搜索 API。
我知道 ES 在与 Nlog 集成时将时间戳存储在 UTC 中。
但是,我需要在此 @timestamp 字段中进行日期范围搜索。
我写了以下查询:
从搜索日期开始:
qcd.DateRange(r => r
.Field(f => f.timestamp)
.GreaterThanOrEquals(searchFromDateTime)
.TimeZone("+02:00")
);
截至日期搜索:
qcd.DateRange(r => r
.Field(f => f.timestamp)
.LessThanOrEquals(searchToDateTime)
.TimeZone("+02:00")
);
以下是查询的其余部分:
searchResponse = (SearchResponse<SearchEventDto>)client.Search<SearchEventDto>(s => s
.Index("logstash-*")
.Type("logevent")
.Query(q => qcd)
);
SearchFromDateTime 或 SearchToDateTime 是 c# 日期。
很明显,查询有问题,因为它没有考虑时差。
例如,由于我是中欧时间,如果我输入 28.06.2019 14:48 作为搜索起始日期,它应该从 28.06.2019 12:48 开始搜索。或者,同样的情况也应该发生在搜索到日期中。
知道吗,我该如何实现?
理论上应该是这样的。以下弹性查询
"query": {
"range": {
"publication_date": {
"gte": "2012-05-29T01:00:00",
"lte": "2012-05-29T01:00:00",
"time_zone": "+01:00"
}
}
}
给我的文件结果为 2012-05-29T00:00:00。
请确认一下,您是否同时使用了 From 和 To 部分?在那种情况下,我相信第二个会覆盖第一个并且应该合并为一个查询。
如果您在 ConnectionSettings 中启用 EnableDebugMode()
(或使用 client.RequestResponseSerializer.SerializeToString(...);
手动序列化查询),序列化查询会是什么样子。
也许 c# 日期不符合预期?
我已经为您准备了一个工作示例,也许您可以在您的案例中找到问题所在。如果没有,请使用您希望通过查询找到的示例文档更新问题。
class Program
{
public class Document
{
public int Id { get; set; }
public DateTime Timestamp { get; set; }
}
static async Task Main(string[] args)
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(pool);
connectionSettings.DefaultIndex("documents");
//only for debbuging purpose, don't use in production
connectionSettings.DisableDirectStreaming();
connectionSettings.PrettyJson();
var client = new ElasticClient(connectionSettings);
await client.Indices.DeleteAsync("documents");
await client.Indices.CreateAsync("documents");
var response = await client.IndexAsync(
new Document {Id = 1, Timestamp = new DateTime(2010, 01, 01, 10, 0, 0)}, descriptor => descriptor);
var searchResponse = await client.SearchAsync<Document>(s => s
.Query(q => q
.Bool(b => b
//I'm using date range in filter context as I don't want elasticsearch
//to calculate score for each document found,
//should be faster and likely it will be cached
.Filter(f =>
f.DateRange(dt => dt
.Field(field => field.Timestamp)
.LessThanOrEquals(new DateTime(2010, 01, 01, 11, 0, 0))
.TimeZone("+1:00"))))));
//prints 1
Console.WriteLine(searchResponse.Documents.Count);
}
}
希望对您有所帮助。
我正在尝试使用 NEST 在弹性搜索中使用日期范围搜索 API。
我知道 ES 在与 Nlog 集成时将时间戳存储在 UTC 中。 但是,我需要在此 @timestamp 字段中进行日期范围搜索。
我写了以下查询:
从搜索日期开始:
qcd.DateRange(r => r
.Field(f => f.timestamp)
.GreaterThanOrEquals(searchFromDateTime)
.TimeZone("+02:00")
);
截至日期搜索:
qcd.DateRange(r => r
.Field(f => f.timestamp)
.LessThanOrEquals(searchToDateTime)
.TimeZone("+02:00")
);
以下是查询的其余部分:
searchResponse = (SearchResponse<SearchEventDto>)client.Search<SearchEventDto>(s => s
.Index("logstash-*")
.Type("logevent")
.Query(q => qcd)
);
SearchFromDateTime 或 SearchToDateTime 是 c# 日期。
很明显,查询有问题,因为它没有考虑时差。
例如,由于我是中欧时间,如果我输入 28.06.2019 14:48 作为搜索起始日期,它应该从 28.06.2019 12:48 开始搜索。或者,同样的情况也应该发生在搜索到日期中。
知道吗,我该如何实现?
理论上应该是这样的。以下弹性查询
"query": {
"range": {
"publication_date": {
"gte": "2012-05-29T01:00:00",
"lte": "2012-05-29T01:00:00",
"time_zone": "+01:00"
}
}
}
给我的文件结果为 2012-05-29T00:00:00。
请确认一下,您是否同时使用了 From 和 To 部分?在那种情况下,我相信第二个会覆盖第一个并且应该合并为一个查询。
如果您在 ConnectionSettings 中启用 EnableDebugMode()
(或使用 client.RequestResponseSerializer.SerializeToString(...);
手动序列化查询),序列化查询会是什么样子。
也许 c# 日期不符合预期?
我已经为您准备了一个工作示例,也许您可以在您的案例中找到问题所在。如果没有,请使用您希望通过查询找到的示例文档更新问题。
class Program
{
public class Document
{
public int Id { get; set; }
public DateTime Timestamp { get; set; }
}
static async Task Main(string[] args)
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(pool);
connectionSettings.DefaultIndex("documents");
//only for debbuging purpose, don't use in production
connectionSettings.DisableDirectStreaming();
connectionSettings.PrettyJson();
var client = new ElasticClient(connectionSettings);
await client.Indices.DeleteAsync("documents");
await client.Indices.CreateAsync("documents");
var response = await client.IndexAsync(
new Document {Id = 1, Timestamp = new DateTime(2010, 01, 01, 10, 0, 0)}, descriptor => descriptor);
var searchResponse = await client.SearchAsync<Document>(s => s
.Query(q => q
.Bool(b => b
//I'm using date range in filter context as I don't want elasticsearch
//to calculate score for each document found,
//should be faster and likely it will be cached
.Filter(f =>
f.DateRange(dt => dt
.Field(field => field.Timestamp)
.LessThanOrEquals(new DateTime(2010, 01, 01, 11, 0, 0))
.TimeZone("+1:00"))))));
//prints 1
Console.WriteLine(searchResponse.Documents.Count);
}
}
希望对您有所帮助。