Удаление Solr с пользовательским полным импортом

Я пытаюсь использовать DataImportHandler для синхронизации моего индекса с базой данных SQL (что, на мой взгляд, довольно ванильно). Поскольку моя база данных будет довольно большой, я хочу использовать добавочный импорт, используя этот метод http://wiki.apache.org/solr/DataImportHandlerDeltaQueryViaFullImport, поэтому вызовы имеют форму http://localhost:8983/solr/Items/dataimport?command=full-import&clean=false. Это отлично работает для добавления элементов.

У меня есть отдельная таблица DeletedItems в моей базе данных, которая содержит первичные ключи элементов, которые были удалены из таблицы Items, а также время их удаления. В рамках вызова DataImport я надеялся, что смогу удалить соответствующие элементы из моего индекса на основе запроса в соответствии со строками

SELECT Id FROM DeletedItems WHERE WasDeletedOn > '${dataimporter.last_index_time}'

но я не могу понять, как это сделать. Ссылка выше намекает на это с загадочным

В данном случае это, очевидно, означает, что если вы также хотите использовать deletePkQuery, то при выполнении команды delta-import все равно необходимо.

но установка deletePkQuery для приведенного выше SQL-запроса, похоже, не работает. Затем я прочитал, что deletePkQuery работает только с дельта-импортом, поэтому я вынужден делать два запроса на мой solr-сервер как часть процесса синхронизации? Это кажется неправильным, так как операции параметризуются свойством dataimporter.last_index_time, которое изменяется. Оба шага должны быть выполнены в одном «атомарном» действии, верно? Есть идеи?


person Chris Kerridge    schedule 23.07.2016    source источник


Ответы (2)


Вы должны использовать специальные команды обработчика импорта

https://wiki.apache.org/solr/DataImportHandler#Special_Commands

С помощью этих команд вы можете изменить увеличение или удалить документ, поступающий из набора записей полного запроса на импорт. Имейте в виду, что вы должны использовать поле $skipDoc, чтобы избежать повторной индексации документа, и что вы должны повторить идентификатор в поле $deleteDocById.

Вы можете использовать запрос на объединение

select 
  id, 
  text, 
  'false' as [$deleteDocById],
  'false' as [$skipDoc]
from [rows to update or add]
Union Select
   id, 
   '' as text,
   id as [$deleteDocById],
   true as [$skipDoc]

или случай, когда

select
  id,
  text,
  CASE
    when deleted = 1 then id
    else 'false'
  END as [$deleteDocById],
  CASE
    when deleted = 1 then 'true'
    else 'false'
  END as [$skipDoc]
  Where updated > ${dih.last_index_time}
person Jokin    schedule 16.02.2017

deletedPkQuery запускается как часть обычного вызова delta-import, поэтому вам не нужно ничего запускать дважды (и при выполнении полного импорта нет необходимости запускать deletePkQuery, так как все соединение очищается перед импортом в любом случае).

deletedPkQuery должен быть настроен на тот же элемент, что и ваш основной запрос. Убедитесь, что имена полей точно совпадают, и что id, созданный вашим deletePkQuery, совпадает с именем, предоставленным основным запросом.

Там есть минимальный пример на solr.pl для импорта и удаления полей с использованием той же структуры таблицы delete_entries, что и здесь:

<entity 
  name="album" 
  query="SELECT * from albums"
  deletedPkQuery="SELECT deleted_id as id FROM deletes WHERE deleted_at > '${dataimporter.last_index_time}'"
>

Также убедитесь, что формат поля delete_at сопоставим со значением, созданным last_index_time. По умолчанию yyyy-MM-dd HH:mm:ss.

.. и, наконец, помните, что свойство last_index_time недоступно до второго запуска задачи, поскольку при первом заполнении индекса нет «предыдущего времени индекса» (но deletedPkQuery все равно не должен запускаться до этого ).

person MatsLindh    schedule 23.07.2016
comment
Спасибо за ответ. Однако я пытаюсь избежать дельта-импорта, поскольку они, кажется, вызывают вызов базы данных для каждого PK, возвращаемого запросом deltaQuery (таким образом, n + 1), когда подойдет один. Из документации Solr: Примечание. Существует альтернативный подход к обновлению документов в Solr, который во многих случаях более эффективен и требует меньшей настройки, описанной в wiki.apache.org/solr/DataImportHandlerDeltaQueryViaFullImport . Метод, который они там объясняют, очень хорошо работает для добавочного импорта, но я не могу понять, как они намерены настраивать удаление. - person Chris Kerridge; 23.07.2016
comment
Обратите внимание, что используется полный импорт, но он не очищает индекс, а просто добавляет/обновляет документы. - person Chris Kerridge; 23.07.2016
comment
Ах, хороший момент. Я упустил эту деталь. Я думаю, вам придется ввести две команды: одну для полного импорта, затем одну дельта-импорт для последующего удаления. Удаление с полным импортом обычно обрабатывается с помощью clean=true. Чтобы удаления работали с помощью метода, описанного в DeltaQueryViaFullImport, вам придется обрабатывать их вручную (с помощью удаленного поля, которое вы затем очищаете с помощью deleteByQuery или с помощью запроса дельта-импорта, который запускает удаление). Сколько документов вы удаляете между импортами? - person MatsLindh; 24.07.2016
comment
Пользователи будут загружать потенциально очень много элементов, связанных с датой, которые они могут удалить (я также рассматриваю возможность очистки просроченных элементов, чтобы индекс оставался небольшим). Я хотел бы, чтобы они были доступны для поиска как можно скорее, поэтому я планирую запланировать регулярные вызовы для обновления из БД. Само приложение будет выполнять рутинные вызовы БД, поэтому в идеале я хотел бы избежать соединений, перехватывающих дельта-импорт с их вызовами n + 1. Второй «постимпортный» вызов дельта-импорта вызывает у меня беспокойство из-за условий гонки. Кажется, мне может понадобиться немного настроить Java в DIH, но тогда синхронизация с БД кажется рутинным вариантом использования... - person Chris Kerridge; 24.07.2016