Выберите сотрудников с менее чем 10 отпусками в заданном диапазоне дат

У меня есть документ со структурой ниже

{
   id:1,
   leaves:[
            {
               "reason":"",
               "date":"2019-01-01"
            },
            {
               "reason":"",
               "date":"2019-04-30"
            }
          ]
}

листья - это вложенный документ. Структура документа может быть изменена. Мне нужно выбрать сотрудников с менее чем 10 отпусками в заданном диапазоне с 01.01.2019 по 30.05.2019.

Я попробовал агрегацию селектора корзины, но путь корзины «min_bucket» не указывал на пустые корзины (необходим там, где нет листьев, присутствующих в диапазоне). Я получил ответ ниже, и никакие записи не были возвращены.

  "max_hourly_inner" : {
              "value" : null,
              "keys" : [ ]
            }
1
0
109
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Я решаю уравнение показать мне список студентов, у которых меньше 2 отпусков в указанном диапазоне дат, то есть от 2019-04-01 до 2019-05-30

Образцы документов:

// This student has 3 leaves over all and all 3 leaves in the specified date 
POST myleaves/_doc/1
{
  "id": 1001,
  "leaves" : [
    {
      "reason" : "",
      "date" : "2019-04-01"
    },
    {
      "reason" : "",
      "date" : "2019-04-29"
    },
    {
      "reason" : "",
      "date" : "2019-04-30"
    }
  ]
}

//This student has 4 leaves out of which 2 are in specified date range
POST myleaves/_doc/2
{
  "id": 1002,
  "leaves" : [
    {
      "reason" : "",
      "date" : "2019-04-01"
    },
    {
      "reason" : "",
      "date" : "2019-04-04"
    },
    {
      "reason" : "",
      "date" : "2019-07-29"
    },
    {
      "reason" : "",
      "date" : "2019-07-30"
    }
  ]
}

// This student has one leave but no leaves in specified date range
POST myleaves/_doc/3
{
  "id": 1003,
  "leaves":[
    {
      "reason" : "",
      "date" : "2019-07-29"
    }
  ]
}

//This student has no leaves at all
POST myleaves/_doc/4
{
  "id": 1004,
  "leaves":[

    ]
}

Ниже представлена ​​структура запроса агрегации

- Terms Aggregation on `id` field
 - Nested Aggregation on `leaves` field
  - Date Range aggregation on `leaves.date` field
   - Bucket Selector Aggregation on `count`. This is the part where we specify our condition 
 - Bucket Selector Aggregation to retrieve only documents having one bucket. (To avoid showing bucket with 0 doc counts) 

Совокупный запрос:

POST <your_index_name>/_search
{  
   "size":0,
   "aggs":{  
      "mystudents":{  
         "terms":{  
            "field":"id",
            "size":10
         },
         "aggs":{  
            "mycount":{  
               "nested":{  
                  "path":"leaves"
               },
               "aggs": {
                 "valid_dates": {
                   "date_range": {
                     "field": "leaves.date",
                     "ranges": [
                       {
                         "from": "2019-04-01",
                         "to": "2019-05-30"
                       }
                     ]
                   },
                   "aggs": {
                     "myselector": {
                       "bucket_selector": {
                         "buckets_path": {
                           "myparams": "_count"
                         },
                         "script": "params.myparams <= 2"    <---- You may have to change this for less than 10 leaves params.myparams <=10
                       }
                     }
                   }
                 }
               }
            },
            "mybucket_selector":{  
               "bucket_selector":{  
                  "buckets_path":{  
                     "my_bucket_count":"mycount>valid_dates._bucket_count"
                  },
                  "script":"params.my_bucket_count == 1"
               }
            }
         }
      }
   }
}

Обратите внимание на комментарий, который я упомянул в запросе агрегации.

Совокупный ответ:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "mystudents" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 1002,
          "doc_count" : 1,
          "mycount" : {
            "doc_count" : 4,                                 <----- Total Count of Leaves 
            "valid_dates" : {
              "buckets" : [
                {
                  "key" : "2019-04-01T00:00:00.000Z-2019-05-30T00:00:00.000Z",
                  "from" : 1.5540768E12,
                  "from_as_string" : "2019-04-01T00:00:00.000Z",
                  "to" : 1.5591744E12,
                  "to_as_string" : "2019-05-30T00:00:00.000Z",
                  "doc_count" : 2                            <------ Count of leaves in specified range
                }
              ]
            }
          }
        },
        {
          "key" : 1003,
          "doc_count" : 1,
          "mycount" : {
            "doc_count" : 1,
            "valid_dates" : {
              "buckets" : [
                {
                  "key" : "2019-04-01T00:00:00.000Z-2019-05-30T00:00:00.000Z",
                  "from" : 1.5540768E12,
                  "from_as_string" : "2019-04-01T00:00:00.000Z",
                  "to" : 1.5591744E12,
                  "to_as_string" : "2019-05-30T00:00:00.000Z",
                  "doc_count" : 0
                }
              ]
            }
          }
        },
        {
          "key" : 1004,
          "doc_count" : 1,
          "mycount" : {
            "doc_count" : 0,
            "valid_dates" : {
              "buckets" : [
                {
                  "key" : "2019-04-01T00:00:00.000Z-2019-05-30T00:00:00.000Z",
                  "from" : 1.5540768E12,
                  "from_as_string" : "2019-04-01T00:00:00.000Z",
                  "to" : 1.5591744E12,
                  "to_as_string" : "2019-05-30T00:00:00.000Z",
                  "doc_count" : 0
                }
              ]
            }
          }
        }
      ]
    }
  }
}

Если посмотреть на ответ,

  • 1001не появился так как у него было более 2-х листьев в указанном диапазоне дат,
  • 1002появляется, потому что у него было ровно 2 листа из 4 листьев, которые он взял в указанном диапазоне дат
  • 1003 и 1004появляется, так как они не взяли ни одного листа в указанном диапазоне.

Пункт - выбрать студентов с менее чем двумя отпусками (включая студентов, которые не брали ни одного отпуска) в указанном диапазоне дат.

Надеюсь это поможет!

Спасибо за ответ. @Kamal, можете ли вы предложить какие-либо приложения с открытым исходным кодом (доступен исходный код), которые используют эластичный поиск NEST, чтобы я мог изучить передовые методы построения запросов.

jaspreet chahal 31.05.2019 06:27

Другие вопросы по теме