Solr配置:更新请求处理器详解与高级应用

Solr配置:更新请求处理器详解与高级应用

每个Solr接收到的更新请求都会通过一系列插件处理,这些插件被称为更新请求处理器(Update Request Processors,简称URPs)。

URP概述与价值

更新请求处理器可以用于:

  • 向被索引的文档添加字段
  • 修改特定字段的值
  • 如果传入文档不满足特定条件则丢弃更新
  • 实现文档去重、数据验证、格式转换等功能

实际上,Solr中很多功能都是通过更新请求处理器实现的,因此理解这些插件的工作原理和配置方法非常重要。

URP架构与生命周期

处理器链创建

更新请求处理器作为一个或多个处理器链(UpdateRequestProcessorChain)的一部分被创建。Solr创建一个默认的更新请求处理器链,包含几个实现基本Solr功能的处理器。除非用户选择配置和指定不同的自定义链,否则将使用此默认链处理每个更新请求。

设计模式

每个UpdateRequestProcessor都必须有对应的工厂类,该类继承自UpdateRequestProcessorFactory。这种设计提供两个好处:

  1. 线程安全性:更新请求处理器无需线程安全,因为它只被一个请求线程使用,请求完成后即被销毁
  2. 状态管理:工厂类可以接受配置参数并维护请求间可能需要的任何状态,工厂类必须线程安全

生命周期管理

每个更新请求处理器链在Solr核心加载时构建并缓存,直到核心卸载。solrconfig.xml中指定的每个UpdateRequestProcessorFactory也会被实例化并使用配置进行初始化。

当Solr接收更新请求时:

  1. 查找用于此请求的更新链
  2. 使用对应工厂创建链中指定的每个UpdateRequestProcessor新实例
  3. 将更新请求解析为对应的UpdateCommand对象
  4. 通过链运行这些命令
  5. 每个UpdateRequestProcessor实例负责调用链中的下一个插件
  6. 可以选择短路链(不调用下一个处理器)或抛出异常来终止处理

注意:单个更新请求可能包含多个新文档或删除的批次,因此相应的processXXX方法会为每个单独的更新多次调用,但保证单个线程串行调用这些方法。

更新请求处理器配置

默认更新请求处理器链

如果solrconfig.xml中没有配置更新请求处理器链,Solr会自动创建默认链,按顺序包含以下处理器:

  1. LogUpdateProcessorFactory:跟踪此请求期间处理的命令并记录它们
  2. DistributedUpdateProcessorFactory:负责将更新请求分发到正确的节点,例如将请求路由到正确分片的leader并将更新从leader分发到每个副本(仅在SolrCloud模式下激活)
  3. RunUpdateProcessorFactory:使用内部Solr API执行更新

这些处理器都执行基本功能,因此任何自定义链通常都包含所有这些处理器。RunUpdateProcessorFactory通常是任何自定义链中的最后一个更新处理器。

自定义更新请求处理器链

以下示例演示如何在solrconfig.xml中配置自定义链:

1
2
3
4
5
6
7
8
9
10
11
<updateRequestProcessorChain name="dedupe">
<processor class="solr.processor.SignatureUpdateProcessorFactory">
<bool name="enabled">true</bool>
<str name="signatureField">id</str>
<bool name="overwriteDupes">false</bool>
<str name="fields">name,features,cat</str>
<str name="signatureClass">solr.processor.Lookup3Signature</str>
</processor>
<processor class="solr.LogUpdateProcessorFactory" />
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>

这个示例创建了名为”dedupe”的新更新处理器链,包含SignatureUpdateProcessorFactory、LogUpdateProcessorFactory和RunUpdateProcessorFactory。SignatureUpdateProcessorFactory进一步配置了不同参数,如”signatureField”、”overwriteDupes”等。

注意:此链没有指定DistributedUpdateProcessorFactory。由于此处理器对Solr正常运行至关重要,Solr会在不包含它的任何链中,在RunUpdateProcessorFactory之前自动插入DistributedUpdateProcessorFactory。

重要提醒:不要忘记在solrconfig.xml中定义的任何链末尾添加RunUpdateProcessorFactory,否则该链处理的更新请求不会实际影响索引数据。

将单独的处理器配置为顶级插件

更新请求处理器也可以在solrconfig.xml中独立于链进行配置:

1
2
3
4
5
6
7
8
<updateProcessor class="solr.processor.SignatureUpdateProcessorFactory" name="signature">
<bool name="enabled">true</bool>
<str name="signatureField">id</str>
<bool name="overwriteDupes">false</str>
<str name="fields">name,features,cat</str>
<str name="signatureClass">solr.processor.Lookup3Signature</str>
</updateProcessor>
<updateProcessor class="solr.RemoveBlankFieldUpdateProcessorFactory" name="remove_blanks"/>

然后可以在solrconfig.xml的更新请求处理器链中引用它们:

1
2
3
<updateProcessorChain name="custom" processor="remove_blanks,signature">
<processor class="solr.RunUpdateProcessorFactory" />
</updateProcessorChain>

SolrCloud中的更新处理器

分布式处理机制

在SolrCloud中,更新请求处理器的行为需要特别考虑:

  • DistributedUpdateProcessor之前的处理器:仅在首先接收客户端更新的节点上运行,无论该节点是leader还是副本
  • DistributedUpdateProcessor之后的处理器:仅在leader和副本节点上运行,不在转发节点上执行

处理流程示例

假设3节点SolrCloud集群,节点A托管shard1的leader,节点B托管shard2的leader,节点C托管shard2的NRT副本。更新请求发送到节点A,然后转发到节点B,再分发到节点C:

节点A:运行SignatureUpdateProcessor(计算签名并放入”id”字段),然后LogUpdateProcessor,最后DistributedUpdateProcessor。此处理器确定更新实际属于节点B并转发到节点B。

节点B:接收更新并发现它是由另一个节点转发的。更新直接发送到DistributedUpdateProcessor,因为它已经在节点A上经过SignatureUpdateProcessor处理。

节点C:接收更新并发现它是由leader分发的。更新直接发送到DistributedUpdateProcessor进行一致性检查。

预处理器和后处理器配置

可以使用”post-processor”属性配置后处理器:

1
2
3
<updateProcessorChain name="custom" processor="signature" post-processor="remove_blanks">
<processor class="solr.RunUpdateProcessorFactory" />
</updateProcessorChain>

重要警告:在恢复期间,自定义更新链后处理器永远不会在恢复的副本上调用缓冲的更新请求。因此,避免在自定义更新链中指定后处理器。

原子更新处理器工厂

如果AtomicUpdateProcessorFactory在DistributedUpdateProcessor之前的更新链中,传入链的文档将是部分文档。由于DistributedUpdateProcessor负责在leader节点上将原子更新处理为完整文档,这意味着仅在转发节点上执行的预处理器只能操作部分文档。如果处理器必须处理完整文档,唯一选择是将其指定为后处理器。

使用自定义链

update.chain请求参数

可以在任何更新请求中使用update.chain参数选择在solrconfig.xml中配置的自定义链:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl "http://localhost:8983/solr/gettingstarted/update/json?update.chain=dedupe&commit=true" \
-H 'Content-type: application/json' \
-d '[
{
"name" : "The Lightning Thief",
"features" : "This is just a test",
"cat" : ["book","hardcover"]
},
{
"name" : "The Lightning Thief",
"features" : "This is just a test",
"cat" : ["book","hardcover"]
}
]'

processor和post-processor请求参数

可以使用processor和post-processor请求参数动态构造自定义更新请求处理器链:

1
2
3
4
5
6
7
8
9
# 作为预处理器执行
curl "http://localhost:8983/solr/gettingstarted/update/json?processor=remove_blanks,signature&commit=true" \
-H 'Content-type: application/json' \
-d '[...]'

# 作为预处理器和后处理器执行
curl "http://localhost:8983/solr/gettingstarted/update/json?processor=remove_blanks&post-processor=signature&commit=true" \
-H 'Content-type: application/json' \
-d '[...]'

配置自定义链为默认值

可以指定自定义链作为特定更新处理器的默认值,而不是在每个请求的请求参数中指定名称。

通过initParams配置:

1
2
3
4
5
<initParams path="/update/**">
<lst name="defaults">
<str name="update.chain">add-unknown-fields-to-the-schema</str>
</lst>
</initParams>

通过默认值配置:

1
2
3
4
5
<requestHandler name="/update/extract" startup="lazy" class="solr.extraction.ExtractingRequestHandler">
<lst name="defaults">
<str name="update.chain">add-unknown-fields-to-the-schema</str>
</lst>
</requestHandler>

内置更新请求处理器工厂

通用更新处理器工厂

AddSchemaFieldsUpdateProcessorFactory
动态向模式添加字段,如果输入文档包含不匹配模式中任何字段或动态字段的字段。

AtomicUpdateProcessorFactory
将常规字段值文档转换为原子更新文档。可以在运行时使用,无需在solrconfig.xml中定义。

ClassificationUpdateProcessorFactory
使用Lucene的分类模块提供简单文档分类。

CloneFieldUpdateProcessorFactory
将任何匹配源字段中找到的值克隆到配置的目标字段中。

DefaultValueUpdateProcessorFactory
向fieldName中没有值的任何文档添加默认值的简单处理器。

DocBasedVersionConstraintsProcessorFactory
帮助基于每个文档的版本号使用配置的versionField名称对文档实施版本约束。

DocExpirationUpdateProcessorFactory
管理文档自动”过期”的更新处理器工厂。

FieldNameMutatingUpdateProcessorFactory
通过用配置的替换替换所有与配置模式的匹配来修改字段名。

IgnoreCommitOptimizeUpdateProcessorFactory
在SolrCloud模式下运行时,允许忽略客户端应用程序的提交和/或优化请求。

IgnoreLargeDocumentProcessorFactory
防止大小超过限制(以KB为单位)的大文档被索引。

NumFieldLimitingUpdateRequestProcessorFactory
一旦核心超过可配置的”最大”字段数,就会使更新请求失败。

RegexpBoostProcessorFactory
将”inputField”的内容与”boostFilename”中找到的正则表达式匹配,如果匹配将从文件返回相应的boost值并输出到”boostField”作为double值。

SignatureUpdateProcessorFactory
使用定义的字段集为文档生成哈希”签名”。对于只索引”相似”文档的一个副本很有用。

ScriptUpdateProcessorFactory
启用使用作为脚本实现的更新处理器的处理器。

TemplateUpdateProcessorFactory
允许基于模板模式向文档添加新字段。此更新处理器也可以在运行时使用。

TimestampUpdateProcessorFactory
向添加的任何在指定字段中没有值的文档添加新生成的”NOW”日期值的更新处理器。

URLClassifyProcessorFactory
检查URL并输出到具有该URL特征的各种其他字段的更新处理器。

UUIDUpdateProcessorFactory
向添加的任何在指定字段中没有值的文档添加新生成的UUID值的更新处理器。

字段变异更新处理器工厂

这些工厂都提供在索引时修改文档中字段的功能:

  • ConcatFieldUpdateProcessorFactory:使用可配置分隔符连接多个值
  • CountFieldValuesUpdateProcessorFactory:用值数量的计数替换任何值列表
  • FieldLengthUpdateProcessorFactory:用CharSequences的长度替换字符序列值
  • FirstFieldValueUpdateProcessorFactory:只保留第一个值
  • HTMLStripFieldUpdateProcessorFactory:剥离所有HTML标记
  • IgnoreFieldUpdateProcessorFactory:忽略并删除匹配字段
  • LastFieldValueUpdateProcessorFactory:只保留最后一个值
  • MaxFieldValueUpdateProcessorFactory:保留最大值
  • MinFieldValueUpdateProcessorFactory:保留最小值
  • ParseBooleanFieldUpdateProcessorFactory:转换为Boolean值
  • ParseDateFieldUpdateProcessorFactory:转换为Date值
  • ParseNumericFieldUpdateProcessorFactory:各种数字类型转换
  • PreAnalyzedUpdateProcessorFactory:解析预分析字段
  • RegexReplaceProcessorFactory:正则表达式替换
  • RemoveBlankFieldUpdateProcessorFactory:删除空白值
  • TrimFieldUpdateProcessorFactory:修剪前后空白
  • TruncateFieldUpdateProcessorFactory:截断到最大字符长度
  • UniqFieldsUpdateProcessorFactory:删除重复值

运行时更新处理器

这些处理器不需要在solrconfig.xml中进行任何配置,当它们的名称添加到随更新请求发送的处理器参数时会自动初始化。

AtomicUpdateProcessorFactory

使用参数processor=atomic调用。用于将普通更新操作转换为原子更新操作:

1
processor=atomic&atomic.field1=add&atomic.field2=set&atomic.field3=inc&atomic.field4=remove

TemplateUpdateProcessorFactory

使用参数processor=template调用。基于模板模式向文档添加新字段:

1
processor=template&template.field=fullName:Mr. {firstName} {lastName}

UUIDUpdateProcessorFactory

使用参数processor=uuid调用。向文档添加生成的UUID:

1
processor=uuid&uuid.fieldName=somefield_name

最佳实践

1. 链设计原则

  • 总是以RunUpdateProcessorFactory结尾
  • 考虑SolrCloud环境中的分布式处理
  • 合理安排预处理器和后处理器的顺序

2. 性能优化

  • 在转发节点上执行计算密集型处理器以分散负载
  • 避免在后处理器中执行不必要的重复计算
  • 使用合适的字段选择器来限制处理器作用范围

3. 错误处理

  • 实现适当的异常处理逻辑
  • 考虑使用permissive模式处理不完整数据
  • 建立监控和日志记录机制

更新请求处理器是Solr数据处理管道中的核心组件,正确理解和配置这些处理器对于构建高效、可靠的搜索系统至关重要。

© 2025 Solr Community of China All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero