Как правильно выгружать большие объемы данных через REST API из Bitrix24

Часто встает задача импорта каких либо сущностей с портала посредством rest. При этом при большом количестве сущностей прямой подход к задаче, с установкой фильтра и передачей в каждый следующий запрос start = start+50, не оптимальный. Так как, при использование start >= 0 на каждый запрос выполняется еще и запрос подсчета количества элементов удовлетворяющих фильтру. Что при большом количестве элементов, попадающих в него, или при сложной фильтрации работает медленно.

Поэтому в случае если вам не нужно количество элементов ( например вам нужно просто 10 последних записей ) или вы делаете импорт всех записей по фильтру, передавайте start = -1.

Данный параметр отключит выполнение запроса подсчета количества элементов и сильно ускорит выборку.

Для выполнения импорта, при этом необходимо будет отсортировать записи по ID и добавить в фильтр условие ID > значения последнего элемента. И с каждым шагом увеличивать его значение. Значение же последнего элемента брать из последнего значения полученного результата.

Условием остановки импорта будет пустой ответ, или то, что в ответе элементов меньше 50.

Ниже приведен пример кода и сравнение времени выполнения с классическим подходом. Так при 2 387 743 лидах, с одинаковыми правами и фильтром, время выполнения уменьшилось с 49.9 секунд до 0,097 секунд.

Пример:

$tokenID = 'XXXXXXXXXXXXXXXXXXXXX';
$host = 'XXXX.bitrix24.ru';
$user = 1;

/**
 * Начинаем с нуля или с какого то предыдущего шага
 */
$leadID = 0;
$finish = false;

while (!$finish)
{
   /**
    * Выполняем пока не заберем все данные, в этом случае не стоит забывать и про задержку между хитами.
    * Либо каждый раз выбираем только 50, начиная с того элемента, на котором остановилась прошлая итерация
   */

   $http = new \Bitrix\Main\Web\HttpClient();

   $http->setTimeout(5);
   $http->setStreamTimeout(50);

   $json = $http->post(
      'https://'.$host.'/rest/'.$user.'/'.$tokenID.'/crm.lead.list/',
      [
         'order' => ['ID' => 'ASC'],
         'filter' => ['>ID' => $leadID],
         'select' => ['ID', 'TITLE', 'DATE_CREATE'],
         'start' => -1
      ]
   );

   $result = \Bitrix\Main\Web\Json::decode($json);
   if (count($result['result']) > 0)
   {
      foreach ($result['result'] as $lead)
      {
         $leadID = $lead['ID'];
      }
      // Do something
   }
   else
   {
      $finish = true;
   }
}

/*
//Результаты выполнения rest запроса с использованием count.
   Array
   (
      [result] => Array
      (
         [0] => Array()
         [1] => Array()
         .....
         [49] => Array()

      [next] => 50
      [total] => 2387743
      [time] => Array
      (
         [start] => 1581607213.4833
         [finish] => 1581607263.3997
         [duration] => 49.916450023651
         [processing] => 49.899916887283
         [date_start] => 2020-02-13T18:20:13+03:00
         [date_finish] => 2020-02-13T18:21:03+03:00
      )
)

//Результаты выполнения rest запроса без использования count.

   Array
   (
      [result] => Array
      (
         [0] => Array()
         [1] => Array()
         .....
         [1] => Array()

      [total] => 0
      [time] => Array
      (
         [start] => 1581609136.3857
         [finish] => 1581609136.4835
         [duration] => 0.097883939743042
         [processing] => 0.068500995635986
         [date_start] => 2020-02-13T18:52:16+03:00
         [date_finish] => 2020-02-13T18:52:16+03:00
      )
)
*/


Загрузка комментариев...