Передача и сравнение значений даты и времени с разными часовыми поясами в упругом поиске и гнезде - PullRequest
0 голосов
/ 15 февраля 2019

Я пытаюсь передать значение даты и времени в качестве аргумента (значение, не зависящее от часового пояса, которое находится в часовом поясе «UTC») в запросе, который сравнивает аргумент со значением даты и времени (значение, соответствующее часовому поясу, которое находится в часовом поясе '-05: 00') внутри эластичного документа поиска и возвращает документы.

Вопросы:
1. Правильно ли я делаю это в моем коде ниже?
2. Собирается ли ES обрабатывать сложность различных часовых поясов аргумента datetime перед сравнением его со значениями документа datetime?
3. Будет ли ES возвращать документы с исходными значениями часового пояса даты и времени?
4. Любая документация, раскрывающая внутреннюю часть обработки часового пояса экземпляра эластичного поиска?

Приведенный ниже код возвращает значения, но я не уверен, что он достигает желаемой цели.
По этой ссылке , но она ограничена некоторыми основами
Заранее спасибо.

Исходный документ 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));         
}

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Чтобы добавить к ответу Мэтта Джонсона , отправка часового пояса полезна, когда у входной строки даты у вас есть одно смещение часового пояса (или формат не указывает его, например, 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.

Существует некоторая история в сериализации DateTime и DateTimeOffset в клиенте ,Сериализация в 6.x не может быть изменена, за исключением типов свойств DateTime и DateTimeOffset в ваших собственных POCO, с настраиваемым сериализатором , подключенным .Это ограничение , если хотите, не часто является проблемой, однако, поскольку большинство API-интерфейсов в клиенте принимают DateMath тип , где может использоваться форматированная строка даты, которая поддерживает математические выражения даты,В DateMath существуют неявные преобразования из DateTime и string, а также методы для построения более сложных выражений.

0 голосов
/ 16 февраля 2019

Из документа, на который вы дали ссылку:

, теперь параметр time_zone не влияет (даты должны быть сохранены как UTC)

Из этого идругие примеры на этой странице показывают, что параметр time_zone (или .TimeZone(...) в C #) влияет на входные значения запроса.Передав +00:00, вы говорите, что входные значения не нуждаются в корректировке.

Сами даты должны быть сохранены в документе как UTC для правильного выполнения запроса диапазона.Вы не должны хранить var_time как 2018-04-24T17:05:13.082-05:00, а как 2018-04-24T17:10:13.082Z.Затем вы можете запросить его.

При необходимости сохраните два поля, чтобы у вас было одно поле для запроса и одно для отображения исходного местного времени.

Чтобы ответить на ваши конкретные вопросы:

  1. Правильно ли я делаю это в приведенном ниже коде?

Ваш запрос в порядке, но .TimeZone("+00:00") не требуется, поскольку он ничего не настраиваетаргументы.Однако вам необходимо убедиться, что отметка времени в документе хранится в формате UTC.

Собирается ли ES обрабатывать сложность различных часовых поясов аргумента datetime перед сравнением его со значениями документа datetime?

Это просто удобство для настройки аргументов.Не корректирует значение в документе.

Будет ли ES возвращать документы с исходными значениями часового пояса даты и времени?

Документ должен быть возвращен в обычном режиме.Изменение часового пояса в запросе не влияет на это.

Есть какая-нибудь документация, раскрывающая внутреннюю часть обработки часового пояса экземпляра эластичного поиска?

Я не смог найти ничего за пределами документа, с которым вы связаны.Вы должны поэкспериментировать, чтобы подтвердить любые предположения.

...