Elasticsearch запрашивает количество дат в массиве, соответствующем запросу - PullRequest
1 голос
/ 31 мая 2019

У меня есть документы в следующей форме

PUT test_index/_doc/1
{
    "dates" : [
      "2018-07-15T14:12:12",
      "2018-09-15T14:12:12",
      "2018-11-15T14:12:12",
      "2019-01-15T14:12:12",
      "2019-03-15T14:12:12",
      "2019-04-15T14:12:12",
      "2019-05-15T14:12:12"],
    "message" : "hello world"
}

Как запросить документы, в которых n число дат в массиве dates, попадающих между двумя указанными датами?

Например: Найти все документы с 3 датами в массиве dates, находящимся между "2018-05-15T14:12:12" и "2018-12-15T14:12:12" - это должно вернуть вышеуказанный документ как "2018-07-15T14:12:12", "2018-09-15T14:12:12" и "2018-11-15T14:12:12" fallмежду "2018-05-15T14:12:12" и "2018-12-15T14:12:12".

Ответы [ 3 ]

1 голос
/ 31 мая 2019

Я недавно столкнулся с той же проблемой. Однако придумали два решения.

1) Если вы не хотите изменять текущее сопоставление, вы можете запросить документы, используя query_string. Также обратите внимание, что вам нужно будет создать объект запроса в соответствии с имеющимся у вас диапазоном. ( "\" 2019-04-08 \ "ИЛИ \" 2019-04-09 \ "ИЛИ \" 2019-04-10 \ "" )

      {
  "query": {
    "query_string": {
      "default_field": "dates",
      "query": "\"2019-04-08\" OR \"2019-04-09\" OR \"2019-04-10\" "
    }
  }
}

Однако этот тип запроса имеет смысл, только если диапазон мал.

2) Второй способ - вложенный. Но вам придется изменить текущее отображение таким образом.

 {
  "properties": {
    "dates": {
      "type": "nested",
      "properties": {
        "key": {
              "type": "date",
              "format": "YYYY-MM-dd"
            }
      }
    }
  }
}

Итак, ваш запрос будет выглядеть примерно так: -

     {
  "query": {
    "nested": {
      "path": "dates",
      "query": {
        "bool": {
          "must": [
            {
              "range": {
                "dates.key": {
                  "gte": "2018-04-01",
                  "lte": "2018-12-31"
                }
              }
            }
          ]
        }
      }
    }
  }
}
0 голосов
/ 31 мая 2019

Я нашел свой собственный ответ на этот вопрос, хотя я не уверен, насколько он эффективен по сравнению с другими ответами:

GET test_index/_search
{
  "query":{
    "bool" : {
        "filter" : {
          "script" : {
            "script" : {"source":"""
            int count = 0;
            for (int i=0; i<doc['dates'].length; ++i) {
              if (params.first_date < doc['dates'][i].toInstant().toEpochMilli() && doc['dates'][i].toInstant().toEpochMilli() < params.second_date) {
                count += 1; 
              }
            }
            if (count >= 2) {
              return true
            } else {
              return false
            }
            """,
            "lang":"painless",
            "params": {
              "first_date": 1554818400000,
              "second_date": 1583020800000
            }
            }
          }
        }
    }
  }
}

, где параметрами являются две даты в эпоху времени.Я выбрал 2 совпадения, но вы можете обобщить их на любое число.

0 голосов
/ 31 мая 2019

Вы можете создать даты в виде вложенного документа и использовать селектор сегментов агрегирование.

{
  "empId":1,
  "dates":[
             { 
               "Days":"2019-01-01"
             },
             { 
               "Days":"2019-01-02"
             }
          ]
}

Отображение:

 "mappings" : {
      "properties" : {
       "empId" : {
              "type" : "keyword"
        },
        "dates" : {
          "type" : "nested",
          "properties" : {
            "Days" : {
              "type" : "date"
            }
          }
        }
     }
  }
GET profile/_search
{
  "query": {
    "bool": {
      "filter": {
        "nested": {
          "path": "dates",
          "query": {
            "range": {
              "dates.Days": {
                "format": "yyyy-MM-dd",
                "gte": "2019-05-01",
                "lte": "2019-05-30"
              }
            }
          }
        }
      }
    }
  },
  "aggs": {
    "terms_parent_id": {
      "terms": {
        "field": "empId"
      },
      "aggs": {
        "availabilities": {
          "nested": {
            "path": "dates"
          },
          "aggs": {
            "avail": {
              "range": {
                "field": "dates.Days",
                "ranges": [
                  {
                    "from": "2019-05-01",
                    "to": "2019-05-30"
                  }
                ]
              },
              "aggs": {
                "count_Total": {
                  "value_count": {
                    "field": "dates.Days"
                  }
                }
              }
            },
            "max_hourly_inner": {
              "max_bucket": {
                "buckets_path": "avail>count_Total"
              }
            }
          }
        },
        "bucket_selector_page_id_term_count": {
          "bucket_selector": {
            "buckets_path": {
              "children_count": "availabilities>max_hourly_inner"
            },
            "script": "params.children_count>=19;"  ---> give the number of days that should match
          }
        },
        "hits": {
              "top_hits": {
                "size": 10   
              }
            }
      }
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...