我正在尝试实现文档的就地更新。
索尔版本 - 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的工作原理:
-
Lucene 索引表示为一组段。此外,每个段本身就是一个自动包含的索引,每个段有多个文件。最后,一旦写入磁盘,段大多是不可变的。
-
每个Solr核心都有一个IndexSearcher实例来执行查询。IndexSearcher 具有创建时存在的所有段的静态视图。此视图在 IndexSearcher 的生存期内不会更改,并且缓存属于 IndexSearcher。
-
每当您发出提交时,都会创建一个新分段。此操作将创建新的索引搜索器以反映新添加(或更新(的文档。当新的 IndexSearcher 正在初始化时,旧的 IndexSearcher 仍在处理请求。一旦新的 IndexSearcher 完成,旧的 IndexSearcher 如果未注册(销毁(,新的 IndexSearcher 开始为查询请求提供服务。
因此,filterCache 被清除,因为它与新的 IndexSearcher 有关。但是您可以使用自动预热:使用旧缓存中的值预填充新缓存(请参阅 solrconfig.xml 中的 autowarmCount(。请注意,因为变暖会影响性能 - 基本上新的IndexSearcher将使用旧IndexSearcher缓存中的键(查询(重新运行一定百分比(可配置(的过滤器查询 - 因为IndexSearcher在变暖完成之前尚未准备就绪。
请参阅:https://wiki.apache.org/solr/SolrCaching#autowarmCount
PS:由于上述原因,通常不建议为每个新文档/更新发出提交。最好依靠自动硬提交和软提交。