使用 solrJ 就地更新

in-place updates using solrJ

我正在尝试实现文档的就地更新。

Solr 版本 - 5.5.2

Schema.xml -

<dynamicField name="store_*" type="int" indexed="false" stored="false" docValues="true"/>
<field name="_version_" type="long" indexed="false" stored="false" docValues="true" multiValued="false"/>

solrconfig.xml -

<updateHandler class="solr.DirectUpdateHandler2">
  <updateLog>
    <str name="dir">${solr.ulog.dir:}</str>
    <int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>
  </updateLog>
</updateHandler>`

正在使用 UpdateHandler - DirectUpdateHandler2

根据 this 文章,目标字段是非索引 (indexed="false")、非存储 (stored="false")、单值 (multiValued="false") 数字docValues (docValues="true") 字段。

我只使用 updateHandler.addDoc(addUpdateCommand); 添加文档并且在添加文档后不执行提交使用 - solrClient.commit();

问题没有提交,文档没有反映。

如果我使用 autoSoftCommit 并且仅添加文档,则更改会反映在索引中,但会清除 filterCache。

我的目标是在不清除 filterCache 的情况下实现就地更新。

这能实现吗?

简短回答:不,您不能在不清除 Solr 缓存的情况下既索引文档(部分或就地更新仍然是索引)又使其可搜索(或可见更改)。

长答案:您可以索引文档并让缓存保持填充状态 (openSearcher=false),但是新索引的文档 不会出现在搜索结果中 除非您执行硬操作或软提交。要了解为什么您应该了解 Solr/Lucene 的工作原理:

  1. Lucene 索引表示为一组段。此外,每个段都是一个自动包含的索引,每个段都有多个文件。最后,一旦写入磁盘,段大部分是不可变的。

  2. 每个 Solr 核心都有一个 IndexSearcher 实例来执行查询。 IndexSearcher 具有创建时存在的所有段的静态视图。 此视图在 IndexSearcher 的生命周期内不会更改,缓存属于 IndexSearcher。

  3. 每当您发出提交时,都会创建一个新段。此操作创建一个新的 IndexSearcher 以反映新添加(或更新)的文档。在初始化新的 IndexSearcher 时,旧的仍在处理请求。一旦新的 IndexSearcher 完成,旧的如果未注册(销毁)并且新的 IndexSearcher 开始服务于查询请求。

因此,filterCache 被清除,因为它属于新的 IndexSearcher。 但是您可以使用 autoWarming:使用旧缓存中的值预填充新缓存(请参阅 autowarmCount solrconfig.xml)。请注意,因为变暖会影响性能——基本上,新的 IndexSearcher 将使用旧 IndexSearcher 缓存中的键(查询)重新 运行 一定百分比(可配置)的过滤器查询——因为 IndexSearcher 直到暖化结束。

参见:https://wiki.apache.org/solr/SolrCaching#autowarmCount

PS:由于上述原因,通常不建议为每个新的 document/update 提交一次。最好依靠自动硬提交和软提交。