使用 solrJ 进行就地更新



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

索尔版本 - 5.5.2

架构.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"/>

索尔配置.xml -

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

正在使用的更新处理程序 - DirectUpdateHandler2

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

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

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

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

我的目标是在不清除过滤器缓存的情况下实现就地更新。

这能实现吗?

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

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

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

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

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

因此,filterCache 被清除,因为它与新的 IndexSearcher 有关。但是您可以使用自动预热:使用旧缓存中的值预填充新缓存(请参阅 solrconfig.xml 中的 autowarmCount(。请注意,因为变暖会影响性能 - 基本上新的IndexSearcher将使用旧IndexSearcher缓存中的键(查询(重新运行一定百分比(可配置(的过滤器查询 - 因为IndexSearcher在变暖完成之前尚未准备就绪。

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

PS:由于上述原因,通常不建议为每个新文档/更新发出提交。最好依靠自动硬提交和软提交。

最新更新