Как обновить документы Solr на стороне сервера Solr с помощью специального обработчика/плагина

У меня есть ядро ​​с миллионами записей.
Я хочу добавить собственный обработчик, который сканирует существующие документы и обновляет одно из полей в зависимости от условия (например, возраст>12).
Я предпочитаю делать это на на стороне сервера Solr, чтобы избежать отправки миллионов документов клиенту и обратно.
Я думал написать плагин solr, который будет получать запрос и обновлять некоторые поля в документах запроса (например, удаление обработчиком запроса).< br> Мне было интересно, существуют ли существующие решения или лучшие альтернативы.
Я некоторое время искал в Интернете и не смог найти примеров подключаемых модулей Solr, которые обновляют документы (мне не нужно расширять обработчик обновлений).
Я написал подключаемый модуль, в котором используется следующий код, который работает нормально, но не так быстро, как мне нужно.
В настоящее время я делаю:

AddUpdateCommand addUpdateCommand = new AddUpdateCommand(solrQueryRequest); 
DocIterator iterator = docList.iterator(); 
SolrIndexSearcher indexReader = solrQueryRequest.getSearcher(); 
while (iterator.hasNext()) { 
   Document document = indexReader.doc(iterator.nextDoc()); 
   SolrInputDocument solrInputDocument = new SolrInputDocument(); 
   addUpdateCommand.clear(); 
   addUpdateCommand.solrDoc = solrInputDocument; 
   addUpdateCommand.solrDoc.setField("id", document.get("id")); 
   addUpdateCommand.solrDoc.setField("my_updated_field", new_value); 
   updateRequestProcessor.processAdd(addUpdateCommand); 
} 

Но это очень дорого, так как обработчик обновления снова извлечет документ, который у меня уже есть под рукой.
Есть ли безопасный способ обновить документ lucene и записать его обратно, принимая во внимание весь код, связанный с Solr, такой как кеши? , дополнительная логика solr и т. д.?
Я думал преобразовать его в SolrInputDocument, а затем просто добавить документ через Solr, но сначала мне нужно преобразовать все поля.
Заранее спасибо, Авнер


person Avner Levy    schedule 17.06.2013    source источник
comment
Вы, вероятно, уже знаете это, но в Solr акт обновления документа на самом деле означает замену исходного документа обновленным документом, содержащим измененные значения. Обычный способ обработки изменений состоит в том, чтобы передать их из исходной системы в индекс, обычно на основе даты или какого-либо другого признака; чтобы как-то не обновлять индекс локально. Можете ли вы дать немного больше контекста для того, что вы пытаетесь сделать?   -  person icey502    schedule 19.06.2013
comment
Я знаю об удалении/добавлении материала. В моем сценарии есть данные, которые существуют только в индексе Solr (вычисляемое поле). Позже мне нужно добавить некоторые данные в поле для всех документов, которые отвечают на запрос на основе вычисляемого поля (в примере поле «Возраст»). Неужели так сложно открыть писатель на стороне Solr и изменить документы?   -  person Avner Levy    schedule 19.06.2013
comment
Я не сталкивался с этим точным сценарием, но предполагая, что триггер для измененного значения (и последующего обновления) сам по себе является обновлением индекса, возможно, эта ссылка будет полезна: stackoverflow.com/questions/6593887/   -  person icey502    schedule 20.06.2013
comment
Спасибо за ссылку, но у меня другой сценарий. Мне нужно изменить все документы в ядре Solr, а не только тот, который обновляется.   -  person Avner Levy    schedule 20.06.2013


Ответы (2)


Я не уверен, что следующее улучшит производительность, но подумал, что это может вам помочь.

Посмотрите на SolrEntityProcessor.

Его описание звучит очень актуально для того, что вы ищете.

This EntityProcessor imports data from different Solr instances and cores. 
The data is retrieved based on a specified (filter) query. 
This EntityProcessor is useful in cases you want to copy your Solr index 
and slightly want to modify the data in the target index. 
In some cases Solr might be the only place were all data is available.

Однако я не смог найти готовую функцию для встраивания вашей логики. Итак, вам, возможно, придется расширить следующий класс.

SolrEntityProcessor и ссылка на исходный код

Возможно, вы знаете, но есть еще пара моментов.

1) Заставьте весь процесс использовать все доступные ядра процессора. Сделайте его многопоточным.

2) Используйте последнюю версию Solr.

3) Поэкспериментируйте с двумя приложениями Solr на разных машинах с минимальной сетевой задержкой. Это будет трудный звонок:

same machine, two processes VS two machines, more cores, but network overhead.

4) Настройте кеш Solr в соответствии с вашим вариантом использования и конкретной реализацией.

5) Еще пара ресурсов: Проблемы производительности Solr и SolrPerformanceFactors

Надеюсь, поможет. Дайте мне знать статистику, несмотря на этот ответ. Мне любопытно, и ваша информация может помочь кому-то позже.

person phanin    schedule 25.10.2013
comment
Спасибо за вашу оценку, я проверю ваши указания и обновлю их, как только сделаю окончательные выводы (включая награду). @фани - person Avner Levy; 27.10.2013

Чтобы указать, куда поместить пользовательскую логику, я бы посоветовал взглянуть на процессор SolrEntityProcessor. в сочетании с с Solr ScriptTransformer.

ScriptTransformer позволяет вычислять каждый объект после его извлечения из источника импорта данных, манипулировать им и добавлять значения настраиваемых полей до того, как новый объект будет записан в solr.

Пример data-config.xml может выглядеть так

<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>

    <script>
    <![CDATA[
        function calculateValue(row)        {
            row.put("CALCULATED_FIELD", "The age is: " + row.get("age"));
            return row;
        }
    ]]>
    </script>

  <document>
    <entity name="sep" processor="SolrEntityProcessor" 
        url="http://localhost:8080/solr/your-core-name" 
        query="*:*"
        wt="javabin"
        transformer="script:calculateValue">
            <field column="ID" name="id" />
            <field column="AGE" name="age" />
            <field column="CALCULATED_FIELD" name="update_field" />
    </entity>
  </document>
</dataConfig>

Как видите, вы можете выполнять любое преобразование данных, которое вам нравится, и оно может быть выражено в javascript. Так что это было бы хорошим моментом, чтобы выразить вашу логику и преобразования.

Вы говорите, что одно ограничение может быть age > 12. Я бы обработал это с помощью атрибута query SolrEntityProcessor. Вы можете написать query=age:[* TO 12], чтобы для обновления считывались только записи с возрастом до 12 лет.

person cheffe    schedule 25.10.2013
comment
Спасибо за вашу оценку, я проверю ваши указания и обновлю их, как только сделаю окончательные выводы (включая награду). @cheffe - person Avner Levy; 27.10.2013