Довольно часто наши клиенты сталкиваются с необходимостью выгрузить информацию о звонках из раздела Call Detail Record к себе. Как вы уже знаете (даже если взять во внимание предыдущую запись в этом блоге, а именно Липкость звонка), вся историческая статистика хранится в базе elasticsearch. В документации вы так же могли увидеть пример получения данных с помощью нашего REST API. Но, что если звонков несколько сотен? Или несколько тысяч? Как правильно получить такой объем данных? Сегодня я расскажу как работать с большими объемами данных.
Scroll
Для получения большого количества данных, в elasticsearch предусмотрен функционал scroll, который мы повторили и в нашем REST API. Рассмотрим на примере:
{
"scroll" : "5m",
"limit": 1000,
"sort": {
"created_time": {
"order": "desc",
"unmapped_type": "boolean"
}
},
"index": "cdr-a",
"query": "*",
"columns": [
"created_time",
"uuid",
"direction",
"duration"
],
"filter": [
{
"bool": {
"must": [
{
"range": {
"created_time": {
"gte": "now/w",
"lte": "now"
}
}
}
]
}
}
]
}
В тело нашего запроса мы добавили 2 новых параметра:
- scroll — как долго на сервере держать результат запроса
- limit — какими порциями возвращать результат запроса
Дальше, выполняем первый запрос с указанным телом на REST API, для простоты я использую консольную утилиту cURL:
curl -s -L -XPOST \
-H 'Content-Type: application/json' \
-H 'X-Access-Token: ciOiJIUzI1NiJ9.jEyM2UxNThjLWVkNzMtNDAwi'\
"https://pre.webitel.com/engine/api/v2/cdr/text" -d@webitel_scroll_request.json
Вместе с результатом, который не будет превышать заданного в limit значения, мы получим _scroll_id.
Теперь все последующие запросы мы выполняем уже с scrollId в теле запроса. Пример:
curl -s -L -XPOST \
-H 'Content-Type: application/json' \
-H 'X-Access-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6I9.IjKpitL05OLjUPeUQyd4E'\
"https://pre.webitel.com/engine/api/v2/cdr/text/scroll" -d '
{
"scroll": "5m",
"scrollId": 'МНОГО_БУКВ_ПОЛУЧЕННОГО_ИД'
}'
Повторяем запрос, пока не заберем все данные с сервера.
Бонус
В качестве бонуса, подготовил небольшой bash скрипт, который с помощью cURL и jq поможет вам выкачать необходимые данные и сохранить в CSV файл:
#!/bin/bash
rm cdr.csv
tmpfile=$(mktemp /tmp/scroll.XXXXXX)
scroll_id=$(curl -s -L -XPOST \
-H 'Content-Type: application/json' \
-H 'X-Access-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEyM2UxNThjLWVkNzMtNDAzOC1hOWExLTA5Y2MxZjk4ZDJmYSIsImV4cCI6MTU0OTQ5MDQwMDAwMCwiZCI6IndlYml0ZWwuZHJydXBpYWguY29tIiwidCI6ImRvbWFpbiIsInYiOjJ9.IjK6q1ra6um1ZJ0_gJImkNcZUpitL05OLjUPeUQyd4E'\
"https://pre.webitel.com/engine/api/v2/cdr/text" -d@webitel_scroll_request.json | tee >(jq -r '.hits.hits[].fields | [.created_time[], .uuid[], .direction[], .duration[]] | @csv' >>cdr.csv) >(jq '.hits.hits | length' >${tmpfile}) | jq ._scroll_id)
size=$(cat ${tmpfile})
total=$size
while [ $size -ge 1000 ]
do
size=$(curl -s -L -XPOST \
-H 'Content-Type: application/json' \
-H 'X-Access-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEyM2UxNThjLWVkNzMtNDAzOC1hOWExLTA5Y2MxZjk4ZDJmYSIsImV4cCI6MTU0OTQ5MDQwMDAwMCwiZCI6IndlYml0ZWwuZHJydXBpYWguY29tIiwidCI6ImRvbWFpbiIsInYiOjJ9.IjK6q1ra6um1ZJ0_gJImkNcZUpitL05OLjUPeUQyd4E'\
"https://pre.webitel.com/engine/api/v2/cdr/text/scroll" -d '
{
"scroll": "5m",
"scrollId": '${scroll_id}'
}' | tee >(jq -r '.hits.hits[].fields | [.created_time[], .uuid[], .direction[], .duration[]] | @csv' >>cdr.csv) | jq '.hits.hits | length')
echo $size
total=$(( $total $size ))
done
echo "$total - done"
rm $tmpfile
exit 0
Тело запроса должно находится в файле webitel_scroll_request.json в возле данного скрипта.
Удачи с запросами!