Подсчет результатов по отфильтрованному и отсортированному запросу - PullRequest
1 голос
/ 15 марта 2019

У меня проблемы с выполнением этого эквивалента в ES:

SELECT COUNT(*)
FROM
(
    SELECT current_place
    FROM `request`
    WHERE user_id = '3'
    ORDER BY asked_at DESC
    LIMIT 10
) sr1
WHERE current_place = '4'

Цель состоит в том, чтобы взять 10 самых последних записей для пользователя (asked_at - поле метки времени) и подсчитать, сколько записей имеет current_place = '4'

В Elasticsearch я сделал это, не заказывая, потому что мне даже не удалось отфильтровать по 10 элементам:

GET /index/type/_search
{
  "size": 10,
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "user_id": 3
          }
        },
        {
          "term": {
            "current_place": 4
          }
        }
      ]
    }
  }
}

Что дает мне:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 54,
    "max_score" : 0.0,
    "hits" : [
      ... truncated, 10 records ...
    ]
  }
}

Как выполнить подсчет упорядоченных и отфильтрованных данных?

EDIT:

Вот пример данных:

1 | 2019-03-13 18:28:17
1 | 2019-01-15 16:48:30
1 | 2019-01-15 16:25:32
1 | 2019-01-15 16:19:36
1 | 2019-01-15 15:43:33
1 | 2019-01-15 15:42:05
4 | 2018-11-22 14:14:03
1 | 2018-09-11 11:36:05
4 | 2018-09-11 11:00:49
1 | 2018-08-31 11:19:17 -> 10th line
1 | 2018-08-31 11:19:17
1 | 2018-08-31 11:09:32
1 | 2018-08-27 10:19:04
4 | 2018-08-23 11:56:27

запрос SQL возвращает 2

1 Ответ

1 голос
/ 17 марта 2019

Это не возможно сasticsearch, если у вас есть n шарды для этого конкретного индекса.

Так что в основном есть функция под названием terminate after, которая доступнас поиском по телу запроса, который будет учитывать только n документов от каждого осколка .Да, это работает на уровне шарда.

Используя, скажем, в моем индексе * шарды 5, я подумал, что могу использовать значение 2 в обновленном ниже запросе, чтобы увидеть, получено ли только 10 документов (5 шардов * 2 документа)но это не работает таким образом, так как один осколок может возвращать только 1 документ, в то время как остальные возвращают 2, где я в конечном итоге получил запрос на агрегирование 9 документов.

Опять же, с меньшим количеством документов от каждого осколка, ваш отсортированный результат может не получить правильные 10 лучших документов.

Запрос агрегации

POST <your_index_name>/_search
{  
   "size":0,
   "terminate_after":2,
   "query":{  
      "bool":{  
         "filter":[  
            {  
               "term":{  
                  "user_id":101
               }
            }
         ]
      }
   },
   "sort":[  
      {  
         "asked_at":{  
            "order":"desc"
         }
      }
   ],
   "aggs":{  
      "filter_current_place":{  
         "filter":{  
            "term":{  
               "current_place":4
            }
         },
         "aggs":{  
            "requiredCount":{  
               "value_count":{  
                  "field":"current_place"
               }
            }
         }
      }
   }
}

Ниже показан мой ответ:

Ответ

{
  "took" : 2,
  "timed_out" : false,
  "terminated_early" : true,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 9,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "filter_current_place" : {
      "doc_count" : 2,
      "requiredCount" : {
        "value" : 2
      }
    }
  }
}

Обратите внимание, что попадания только 9 несмотря наупомянув, что я бы хотел, чтобы с каждого осколка рассматривалось по 2 документа.Конечно, количество показалось правильным, потому что, как уже упоминалось в вопросе, 9-й документ имеет current_place:4.Что, если бы это было на 10-ой позиции !!

Это, вероятно, не правильно и довольно четко, что необходимо сделать на стороне клиента или на уровне обслуживания.

Если это так, то вам потребуется только приведенный ниже запрос и обработать логику агрегирования на основе 10 лучших документов на стороне клиента / сервисном уровне.

Sorted Query

POST <your_index_name>/_search
{  
   "size":10,
   "query":{  
      "bool":{  
         "filter":[  
            {  
               "term":{  
                  "user_id":101
               }
            }
         ]
      }
   },
   "sort":[  
      {  
         "asked_at":{  
            "order":"desc"
         }
      }
   ]
}

Примечание: Единственный возможный способ добиться этого с помощью Elasticsearch с использованием первого упомянутого выше запроса - это то, что ваш индекс имеет толькоsingle shard и вы используете "terminate_after":10

Хотя технически это не так, я надеюсь, что это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...