文档更新 #
一、更新概述 #
1.1 更新类型 #
Solr支持多种更新方式:
| 类型 | 说明 |
|---|---|
| 全量更新 | 覆盖整个文档 |
| 原子更新 | 更新部分字段 |
| 脚本更新 | 使用脚本更新 |
| 增量更新 | 数值增减操作 |
1.2 更新前提 #
- 文档必须有唯一键(uniqueKey)
- 字段必须存储(stored=true)
- 部分更新需要启用DocValues
二、全量更新 #
2.1 覆盖更新 #
bash
# 原文档
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"title": "Solr实战指南",
"author": "张三",
"price": 99.0
}'
# 覆盖更新(会丢失author字段)
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"title": "Solr实战指南(第二版)",
"price": 128.0
}'
2.2 优缺点 #
优点
- 简单直接
- 性能较好
缺点
- 需要获取完整文档
- 可能丢失字段
- 并发更新有风险
三、原子更新 #
3.1 原子更新操作 #
| 操作 | 说明 |
|---|---|
| set | 设置字段值 |
| add | 添加值到多值字段 |
| remove | 从多值字段移除值 |
| removeregex | 正则移除值 |
| inc | 数值递增 |
| setoradd | 设置或添加 |
3.2 set操作 #
bash
# 设置字段值
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"title": {"set": "Solr实战指南(第二版)"}
}'
3.3 add操作 #
bash
# 添加标签
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"tags": {"add": ["推荐", "畅销"]}
}'
3.4 remove操作 #
bash
# 移除标签
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"tags": {"remove": "推荐"}
}'
3.5 inc操作 #
bash
# 数值递增
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"views": {"inc": 1},
"sales": {"inc": 10}
}'
3.6 组合更新 #
bash
# 多个操作组合
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"title": {"set": "Solr实战指南(第二版)"},
"price": {"set": 128.0},
"tags": {"add": "新版"},
"views": {"inc": 1},
"updated_at": {"set": "2026-03-27T10:00:00Z"}
}'
3.7 批量原子更新 #
bash
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '[
{
"id": "book-001",
"views": {"inc": 1}
},
{
"id": "book-002",
"views": {"inc": 1}
}
]'
四、原子更新要求 #
4.1 Schema配置 #
xml
<!-- 字段必须stored -->
<field name="title" type="text_general" indexed="true" stored="true"/>
<!-- 数值字段建议docValues -->
<field name="views" type="pint" indexed="true" stored="true" docValues="true"/>
<field name="price" type="pdouble" indexed="true" stored="true" docValues="true"/>
<!-- 多值字段 -->
<field name="tags" type="string" indexed="true" stored="true" multiValued="true"/>
4.2 solrconfig.xml配置 #
xml
<updateHandler class="solr.DirectUpdateHandler2">
<updateLog>
<str name="dir">${solr.ulog.dir:}</str>
</updateLog>
</updateHandler>
五、脚本更新 #
5.1 基本语法 #
bash
curl -X POST "http://localhost:8983/solr/mycore/update" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"script": {
"source": "ctx._source.views += params.increment",
"params": {
"increment": 1
}
}
}'
5.2 条件更新 #
bash
curl -X POST "http://localhost:8983/solr/mycore/update" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"script": {
"source": "if (ctx._source.price > params.threshold) { ctx._source.premium = true }",
"params": {
"threshold": 100
}
}
}'
5.3 复杂脚本 #
bash
curl -X POST "http://localhost:8983/solr/mycore/update" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"script": {
"source": "ctx._source.tags.add(params.newTag); ctx._source.updated_at = params.now",
"params": {
"newTag": "热门",
"now": "2026-03-27T10:00:00Z"
}
}
}'
六、更新处理器 #
6.1 UpdateRequestProcessorChain #
xml
<updateRequestProcessorChain name="myChain">
<processor class="solr.LogUpdateProcessorFactory"/>
<processor class="solr.DistributedUpdateProcessorFactory"/>
<processor class="solr.RunUpdateProcessorFactory"/>
</updateRequestProcessorChain>
6.2 自定义处理器 #
xml
<updateRequestProcessorChain name="customChain">
<!-- 时间戳处理器 -->
<processor class="solr.TimestampUpdateProcessorFactory">
<str name="fieldName">updated_at</str>
</processor>
<!-- UUID处理器 -->
<processor class="solr.UUIDUpdateProcessorFactory">
<str name="fieldName">id</str>
</processor>
<processor class="solr.RunUpdateProcessorFactory"/>
</updateRequestProcessorChain>
6.3 使用处理器链 #
bash
curl -X POST "http://localhost:8983/solr/mycore/update?processor=customChain" \
-H "Content-Type: application/json" \
-d '{"title": "新文档"}'
七、乐观并发控制 #
7.1 使用_version_ #
bash
# 获取文档版本
curl "http://localhost:8983/solr/mycore/get?id=book-001"
# 响应包含_version_
{
"doc": {
"id": "book-001",
"title": "Solr实战指南",
"_version_": 1234567890
}
}
# 使用版本更新
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "book-001",
"title": "Solr实战指南(第二版)",
"_version_": 1234567890
}'
7.2 版本规则 #
| _version_值 | 行为 |
|---|---|
| > 0 | 必须匹配现有版本 |
| = 0 | 必须不存在 |
| < 0 | 忽略版本检查 |
7.3 冲突处理 #
bash
# 版本冲突响应
{
"responseHeader": {
"status": 409
},
"error": {
"msg": "Document not found for update. id=book-001",
"code": 409
}
}
八、嵌套文档更新 #
8.1 嵌套文档结构 #
json
{
"id": "product-001",
"name": "iPhone 15",
"price": 8999,
"_childDocuments_": [
{
"id": "review-001",
"content": "非常好用",
"rating": 5
},
{
"id": "review-002",
"content": "性价比高",
"rating": 4
}
]
}
8.2 更新嵌套文档 #
bash
# 更新子文档
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "review-001",
"content": {"set": "非常好用,推荐购买"},
"rating": {"set": 5}
}'
九、更新性能优化 #
9.1 批量更新 #
bash
# 批量更新
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d '[
{"id": "book-001", "views": {"inc": 1}},
{"id": "book-002", "views": {"inc": 1}},
{"id": "book-003", "views": {"inc": 1}}
]'
9.2 延迟提交 #
bash
# 批量更新后统一提交
curl -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d @updates.json
curl -X POST "http://localhost:8983/solr/mycore/update?commit=true"
9.3 使用软提交 #
bash
curl -X POST "http://localhost:8983/solr/mycore/update?softCommit=true" \
-H "Content-Type: application/json" \
-d '{"id": "book-001", "views": {"inc": 1}}'
十、更新监控 #
10.1 更新统计 #
bash
curl "http://localhost:8983/solr/mycore/admin/stats?key=updateHandler"
10.2 事务日志监控 #
bash
# 查看事务日志大小
ls -lh server/solr/mycore/data/tlog/
# 查看事务日志数量
ls server/solr/mycore/data/tlog/ | wc -l
十一、实战示例 #
11.1 商品库存更新 #
bash
# 库存扣减
curl -X POST "http://localhost:8983/solr/products/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "product-001",
"stock": {"inc": -1},
"sales": {"inc": 1},
"updated_at": {"set": "2026-03-27T10:00:00Z"}
}'
11.2 文章浏览量更新 #
bash
# 浏览量+1
curl -X POST "http://localhost:8983/solr/articles/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "article-001",
"views": {"inc": 1}
}'
11.3 用户标签更新 #
bash
# 添加用户标签
curl -X POST "http://localhost:8983/solr/users/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "user-001",
"tags": {"add": ["VIP", "活跃用户"]},
"last_active": {"set": "2026-03-27T10:00:00Z"}
}'
11.4 价格更新 #
bash
# 价格调整
curl -X POST "http://localhost:8983/solr/products/update/json/docs" \
-H "Content-Type: application/json" \
-d '{
"id": "product-001",
"price": {"set": 7999.00},
"original_price": {"set": 8999.00},
"discount": {"set": true},
"updated_at": {"set": "2026-03-27T10:00:00Z"}
}'
十二、常见问题 #
12.1 原子更新失败 #
问题:字段未存储
xml
<!-- 错误配置 -->
<field name="title" type="text_general" indexed="true" stored="false"/>
<!-- 正确配置 -->
<field name="title" type="text_general" indexed="true" stored="true"/>
12.2 版本冲突 #
bash
# 处理版本冲突
max_retries=3
for i in $(seq 1 $max_retries); do
version=$(curl -s "http://localhost:8983/solr/mycore/get?id=book-001" | jq '.doc._version_')
result=$(curl -s -X POST "http://localhost:8983/solr/mycore/update/json/docs" \
-H "Content-Type: application/json" \
-d "{\"id\": \"book-001\", \"title\": {\"set\": \"新标题\"}, \"_version_\": $version}")
if echo "$result" | jq -e '.responseHeader.status == 0' > /dev/null; then
echo "更新成功"
break
fi
echo "重试 $i/$max_retries"
sleep 1
done
12.3 性能问题 #
bash
# 减少更新频率,批量处理
# 使用队列缓冲更新请求
# 配置合理的自动提交间隔
十三、总结 #
更新方式对比:
| 方式 | 适用场景 | 性能 |
|---|---|---|
| 全量更新 | 简单场景 | 高 |
| 原子更新 | 部分字段更新 | 中 |
| 脚本更新 | 复杂逻辑 | 低 |
最佳实践:
- 优先使用原子更新
- 批量处理更新请求
- 使用乐观并发控制
- 合理配置提交策略
- 监控更新性能
下一步,让我们学习文档删除!
最后更新:2026-03-27