Solr索引:更新处理器与数据导入完整指南
更新处理器是专门设计用于向索引添加、删除和更新文档的请求处理器。除了导入丰富文档的插件外,Solr原生支持对XML、CSV和JSON结构化文档的索引。
更新处理器概述
基本原理
推荐的请求处理器配置和使用方式是使用基于路径的名称,这些名称映射到请求URL中的路径。也可以通过qt
(查询类型)参数指定请求处理器。
统一更新请求处理器
单个统一的更新请求处理器支持XML、CSV、JSON和javabin更新请求,根据内容流的Content-Type
委托给适当的ContentStreamLoader
。
文档预处理
Solr为更新请求处理器提供了文档预处理插件,称为更新请求处理器,允许在文档被索引或甚至根据schema检查之前对其进行处理。
UpdateRequestHandler配置
基本配置
默认配置文件默认配置了更新请求处理器:
1
| <requestHandler name="/update" class="solr.UpdateRequestHandler" />
|
高级配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <requestHandler name="/update" class="solr.UpdateRequestHandler"> <lst name="defaults"> <str name="update.chain">dedupe</str> <int name="commitWithin">10000</int> </lst> </requestHandler>
<requestHandler name="/update/json" class="solr.UpdateRequestHandler"> <lst name="defaults"> <str name="update.contentType">application/json</str> <str name="update.chain">json-transform</str> </lst> </requestHandler>
<requestHandler name="/update/csv" class="solr.UpdateRequestHandler"> <lst name="defaults"> <str name="update.contentType">text/csv</str> <str name="separator">,</str> <str name="header">true</str> </lst> </requestHandler>
|
XML格式索引更新
添加文档
更新处理器识别的添加文档的XML模式非常直接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <add> <doc> <field name="id">book001</field> <field name="title">Summer of the all-rounder</field> <field name="authors">Patrick Eagar</field> <field name="subject">Sports</field> <field name="dd">796.35</field> <field name="numpages">128</field> <field name="price">12.40</field> <field name="isbn">0002166313</field> <field name="yearpub">1982</field> <field name="publisher">Collins</field> </doc> <doc> <field name="id">book002</field> <field name="title">Another Book</field> <field name="authors">Jane Doe</field> </doc> </add>
|
XML结构要素
<add>
元素:引入一个或多个要添加的文档
<doc>
元素:引入构成文档的字段
<field>
元素:呈现特定字段的内容
add命令可选属性
commitWithin
在指定的毫秒数内添加文档。
1 2 3 4 5 6 7
| <add commitWithin="10000"> <doc> <field name="id">doc1</field> <field name="title">Example Document</field> </doc> </add>
|
overwrite
指示是否应检查唯一键约束以覆盖同一文档的先前版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <add overwrite="false"> <doc> <field name="id">doc1</field> <field name="title">New Document</field> </doc> </add>
<add overwrite="true"> <doc> <field name="id">doc1</field> <field name="title">Updated Document</field> </doc> </add>
|
性能考虑
- 如果有唯一键字段,默认情况下
/update
操作会覆盖索引中具有相同唯一键的任何文档
- 如果没有定义唯一键,索引性能会快一些,因为不需要检查是否有现有文档要替换
- 如果您有唯一键字段但确信可以安全地绕过唯一性检查,可以指定
overwrite="false"
选项
XML更新命令
Commit和Optimize操作
Commit操作
<commit>
操作将自上次提交以来加载的所有文档写入磁盘上的一个或多个段文件。在发出提交之前,新索引的内容对搜索不可见。
1 2 3 4 5
| <commit/>
<commit waitSearcher="true" expungeDeletes="false"/>
|
Optimize操作
<optimize>
操作请求Solr合并内部数据结构。对于大型索引,优化需要一些时间才能完成。
1 2 3 4 5
| <optimize/>
<optimize waitSearcher="true" maxSegments="1"/>
|
警告:您应该只在静态索引上考虑使用优化,即可以作为常规更新进程一部分进行优化的索引。需要NRT功能的应用程序不应使用优化。
Commit和Optimize参数
waitSearcher(默认:true)
阻塞直到打开并注册新的搜索器作为主查询搜索器,使更改可见。
1 2 3 4 5
| <commit waitSearcher="true"/>
<commit waitSearcher="false"/>
|
expungeDeletes(默认:false)
合并具有10%以上已删除文档的段,在此过程中清除已删除的文档。仅适用于<commit>
操作。
1 2
| <commit expungeDeletes="true"/>
|
maxSegments
尽力将段合并到不超过此数量的段,但不保证实现目标。
1 2 3 4 5
| <optimize maxSegments="1"/>
<optimize maxSegments="3"/>
|
删除文档
按ID删除
1 2 3 4 5
| <delete> <id>doc1</id> <id>doc2</id> <id>doc3</id> </delete>
|
按查询删除
1 2 3 4
| <delete> <query>category:outdated</query> <query>price:[* TO 0]</query> </delete>
|
组合删除
1 2 3 4
| <delete> <id>specific_doc</id> <query>status:deleted</query> </delete>
|
完整的XML更新示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?xml version="1.0" encoding="UTF-8"?> <add commitWithin="5000"> <doc> <field name="id">product_001</field> <field name="name">Wireless Headphones</field> <field name="category">Electronics</field> <field name="price">99.99</field> <field name="in_stock">true</field> <field name="description">High-quality wireless headphones with noise cancellation</field> <field name="tags">wireless</field> <field name="tags">audio</field> <field name="tags">headphones</field> </doc> <doc> <field name="id">product_002</field> <field name="name">Updated Product Name</field> <field name="category">Electronics</field> <field name="price">79.99</field> <field name="in_stock">false</field> </doc> </add>
|
批量操作示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?xml version="1.0" encoding="UTF-8"?> <root> <add> <doc><field name="id">1</field><field name="title">Doc 1</field></doc> <doc><field name="id">2</field><field name="title">Doc 2</field></doc> <doc><field name="id">3</field><field name="title">Doc 3</field></doc> </add> <delete> <id>old_doc_1</id> <id>old_doc_2</id> <query>status:deprecated</query> </delete> <commit waitSearcher="true"/> </root>
|
使用cURL进行XML更新
基本添加文档
1 2 3 4 5 6 7 8 9 10
| curl -X POST "http://localhost:8983/solr/collection1/update" \ -H "Content-Type: application/xml" \ -d ' <add> <doc> <field name="id">example_001</field> <field name="title">Example Document</field> <field name="content">This is an example document for Solr indexing.</field> </doc> </add>'
|
从文件上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| cat > documents.xml << 'EOF' <add> <doc> <field name="id">file_001</field> <field name="title">Document from File</field> <field name="content">This document was loaded from a file.</field> </doc> </add> EOF
curl -X POST "http://localhost:8983/solr/collection1/update" \ -H "Content-Type: application/xml" \ --data-binary @documents.xml
|
删除和提交
1 2 3 4 5 6 7 8 9
| curl -X POST "http://localhost:8983/solr/collection1/update" \ -H "Content-Type: application/xml" \ -d '<delete><id>example_001</id></delete>'
curl -X POST "http://localhost:8983/solr/collection1/update" \ -H "Content-Type: application/xml" \ -d '<commit/>'
|
性能优化建议
1. 批量处理
将多个文档组合在单个<add>
请求中,而不是发送多个小的请求。
1 2 3 4 5 6 7 8 9 10 11
| <add> <doc><field name="id">1</field><field name="title">Doc 1</field></doc> <doc><field name="id">2</field><field name="title">Doc 2</field></doc> <doc><field name="id">3</field><field name="title">Doc 3</field></doc> </add>
<add><doc><field name="id">1</field><field name="title">Doc 1</field></doc></add> <add><doc><field name="id">2</field><field name="title">Doc 2</field></doc></add> <add><doc><field name="id">3</field><field name="title">Doc 3</field></doc></add>
|
2. 使用commitWithin
使用commitWithin
而不是频繁的手动提交。
1 2 3 4 5 6 7 8
| <add commitWithin="10000"> <doc><field name="id">1</field><field name="title">Doc 1</field></doc> </add>
<add><doc><field name="id">1</field><field name="title">Doc 1</field></doc></add> <commit/>
|
3. 合理使用overwrite
在批量导入时,如果确信没有重复,可以设置overwrite="false"
提高性能。
4. 监控和调试
使用Solr Admin UI监控索引状态和更新性能。
常见错误和解决方案
1. 编码问题
问题:XML中的特殊字符导致解析错误
解决:确保使用正确的XML编码和转义字符
1 2 3 4 5
| <field name="description"><p>Price: $99 & free shipping!</p></field>
<field name="description"><![CDATA[<p>Price: $99 & free shipping!</p>]]></field>
|
2. 唯一键冲突
问题:重复的唯一键导致文档被覆盖
解决:
- 检查数据源保证ID唯一性
- 使用UUID或时间戳生成唯一ID
- 设置
overwrite="false"
避免意外覆盖
3. 内存不足
问题:大批量数据导入时内存不足
解决:
4. 提交策略问题
问题:频繁提交影响性能
解决:
- 使用
commitWithin
参数
- 配置
autoCommit
策略
- 在非高峰时段进行批量更新
XML更新处理器是Solr数据导入的基础,掌握其使用方法和最佳实践对于构建高效的索引系统至关重要。通过合理的批量处理、提交策略和错误处理,可以实现稳定、高效的数据导入和更新操作。