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