使用 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);
    }
}

希望对您有所帮助。