использование вставки () и выполнение массовой вставки, похоже, не вызывает вставку с разведчиком в Алголию

Я делаю массовую вставку в Laravel, например

\App\Example::insert([
    [
        'name' => 'abc',
        'value' => '123',
    ],
    [
        'name' => 'def',
        'value' => '456',
    ],
    // etc...
]);

Это сделает массовую вставку, один запрос, но все же вставит много строк одновременно.

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

Я не хочу перебирать свои строки и вставлять их по одному, так как это будет стоить дополнительных запросов.


person user2722667    schedule 23.01.2018    source источник


Ответы (2)


Проблема в том, что Laravel Scout создает Algolio Searchable в методе model::created.

Вы можете просмотреть это здесь, в исходном коде.

Поскольку Laravel не порождает события created/updated/deleted в Mass Events, это означает, что Algolio также никогда не получит их.

Один из вариантов обойти это — взять самый последний автоматически увеличивающийся идентификатор, затем после вставки снова взять этот идентификатор, а затем вызвать ->searchable() в отфильтрованном предложении where в отношении, например:

 DB::transaction(function() {
    $currentId = \App\Example::max('id');
    // do the insert
    $lastId = \App\Example::max('id');

    \App\Example::where('id', '>', $currentId)->where('id', '<=', $lastId)->searchable();
 });

Используя transaction, мы гарантируем, что $lastId не будут повреждены параллельными запросами. Таким образом, мы должны выполнить 4 запроса, что все еще номинально по сравнению с возможными десятками или более.

По правде говоря, вы, вероятно, могли бы еще больше упростить этот код.

person Ohgodwhy    schedule 23.01.2018
comment
Но DB::transaction( не заблокирует эту таблицу полностью? Я имею в виду, что если некоторые другие пользователи сделают вставку, это повлияет на идентификатор. Если я правильно понял, DB::transaction откатывается только в случае возникновения исключения - person user2722667; 28.01.2018
comment
@user2722667 user2722667 Нет. В этом случае смысл транзакции заключается в том, чтобы гарантировать, что последний идентификатор не может быть изменен другим параллельным запросом. Вы можете проверить это сами. - person Ohgodwhy; 28.01.2018

Вы можете просто вызвать ->searchable() для коллекции моделей, как упоминает @Ohgodwhy в комментариях. Движок Algolia для Scout будет объединять обновления для нескольких экземпляров модели вместе, сводя общее количество запросов к минимуму.

person John Ellmore    schedule 23.01.2018
comment
На самом деле вы можете вызвать ->searchable() для коллекции. Поэтому, если вы просто используете простой whereBetweenquery с идентификаторами вставленных данных, вы можете просто пакетировать его таким образом. Сверхмощный, особенно когда Scout настроен на использование Queues. - person Ohgodwhy; 23.01.2018
comment
Вы совершенно правы. Я как-то пропустил это в исходном коде. Я обновлю свой ответ. - person John Ellmore; 23.01.2018