如何使用自定义处理程序/插件更新Solr服务器端的Solr文档

时间:2013-06-17 11:53:35

标签: solr solr4

我有一个拥有数百万条记录的核心 我想添加一个自定义处理程序,它扫描现有文档并根据条件更新其中一个字段(例如,年龄> 12)。
我更喜欢在Solr服务器端进行操作,以避免将数百万个文档发送到客户端并返回 我正在考虑编写一个solr插件,它将接收查询并更新查询文档中的一些字段(如查询处理程序删除)。
我想知道是否有现成的解决方案或更好的替代方案 我在网上搜索了一段时间,找不到更新文档的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添加文档,但我需要先转换所有字段。
提前致谢,   阿夫纳

2 个答案:

答案 0 :(得分:0)

我不确定以下内容是否会改善性能,但认为它可能对您有所帮助。

查看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以及sourcecode

的链接

你可能知道,但还有其他几点。

1)使整个过程利用所有可用的cpu核心。使其成为多线程。

2)使用最新版本的Solr。

3)在不同的机器上试用两个Solr应用程序,网络延迟最小。这将是一个艰难的要求:

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

4)以适用于您的用例和特定实现的方式调整Solr cache

5)还有一些资源:Solr Performance ProblemsSolrPerformanceFactors

希望它有所帮助。尽管有这个答案,让我知道统计数据。我很好奇,你的信息可能会帮助别人。

答案 1 :(得分:0)

要指出放置自定义逻辑的位置,我建议您同时查看the SolrEntityProcessor with Solr's ScriptTransformer

ScriptTransformer允许在从dataemport源中提取每个实体后对其进行计算,操作它并在将新实体写入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。我会通过SolrEntityProcessor的query属性来处理这个问题。您可以编写query=age:[* TO 12],以便只读取年龄最大为12的记录进行更新。