Solr索引:更新处理器与数据导入完整指南

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
<!-- 10秒内自动提交 -->
<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
<!-- 合并为1个段 -->
<optimize maxSegments="1"/>

<!-- 合并为3个段 -->
<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
# 创建 XML 文件
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
<!-- 好的做法:使用commitWithin -->
<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">&lt;p&gt;Price: $99 &amp; free shipping!&lt;/p&gt;</field>

<!-- 或者使用CDATA -->
<field name="description"><![CDATA[<p>Price: $99 & free shipping!</p>]]></field>

2. 唯一键冲突

问题:重复的唯一键导致文档被覆盖
解决

  • 检查数据源保证ID唯一性
  • 使用UUID或时间戳生成唯一ID
  • 设置overwrite="false"避免意外覆盖

3. 内存不足

问题:大批量数据导入时内存不足
解决

  • 分批处理数据
  • 调整JVM堆大小
  • 使用流式处理

4. 提交策略问题

问题:频繁提交影响性能
解决

  • 使用commitWithin参数
  • 配置autoCommit策略
  • 在非高峰时段进行批量更新

XML更新处理器是Solr数据导入的基础,掌握其使用方法和最佳实践对于构建高效的索引系统至关重要。通过合理的批量处理、提交策略和错误处理,可以实现稳定、高效的数据导入和更新操作。

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