为什么这个错误发生 #
routing_missing_exception 表示执行操作时缺少必需的路由信息。路由(routing)值用于确定文档存储在哪个分片上,某些操作需要明确指定路由值。
这个错误可能由以下原因引起:
- 缺少路由参数:请求中未提供必需的路由值
- 自定义路由映射:索引配置了自定义路由映射
- 父文档关系:使用父子关系时需要路由值
- 分片路由:操作需要特定分片但未提供路由
- 客户端配置错误:客户端未正确配置路由
- 默认路由不适用:默认路由机制不适用于该操作
如何修复这个错误 #
1. 提供路由值 #
# 在请求中添加路由参数
GET /<index>/_doc/<id>?routing=<routing_value>
POST /<index>/_doc/<id>?routing=<routing_value>
{
"field": "value"
}
2. 使用文档 ID 作为路由 #
# 如果文档 ID 与路由值相同,可以设置默认路由
PUT /<index>/_mapping
{
"settings": {
"index.routing.allocation.include._tier_preference": "data_hot"
}
}
3. 配置映射中的路由 #
# 在索引创建时配置路由
PUT /<index>
{
"mappings": {
"_routing": {
"required": true
}
}
}
4. 查看映射配置 #
# 查看索引的路由配置
GET /<index>/_mapping?filter_path=**._routing
# 查看所有设置
GET /<index>/_settings
5. 更新客户端配置 #
// 在客户端配置路由
IndexRequest request = new IndexRequest("<index>");
request.id("<id>");
request.routing("<routing_value>");
request.source(...);
6. 使用批量 API 时提供路由 #
# 批量操作时为每个文档指定路由
POST /_bulk
{ "index": { "_index": "<index>", "_id": "1", "routing": "user1" } }
{ "field": "value1" }
{ "index": { "_index": "<index>", "_id": "2", "routing": "user2" } }
{ "field": "value2" }
7. 父子文档路由 #
# 对于父子关系,使用父文档 ID 作为路由
POST /<index>/_doc/<child_id>?routing=<parent_id>
{
"join": {
"name": "child",
"parent": "<parent_id>"
},
"field": "value"
}
8. 搜索时使用路由 #
# 搜索时指定路由以提高性能
GET /<index>/_search?routing=<routing_value>
{
"query": {
"match": {
"field": "value"
}
}
}
9. 删除时提供路由 #
# 删除文档时需要路由值
DELETE /<index>/_doc/<id>?routing=<routing_value>
# 或通过查询删除
POST /<index>/_delete_by_query?routing=<routing_value>
{
"query": {
"term": {
"field": "value"
}
}
}
10. 更新时提供路由 #
# 更新文档时需要路由值
POST /<index>/_update/<id>?routing=<routing_value>
{
"doc": {
"field": "new_value"
}
}
11. 配置默认路由 #
# 可以配置一个字段作为默认路由
PUT /<index>
{
"mappings": {
"_routing": {
"required": true,
"path": "user_id"
}
}
}
12. 批量导入时处理路由 #
// 批量导入时为每个文档生成路由
BulkRequest bulkRequest = new BulkRequest();
for (Document doc : documents) {
IndexRequest indexRequest = new IndexRequest("<index>");
indexRequest.id(doc.getId());
indexRequest.routing(doc.getUserId()); // 使用用户 ID 作为路由
indexRequest.source(doc.toJson());
bulkRequest.add(indexRequest);
}
13. 验证路由配置 #
# 确认路由配置正确
GET /<index>/_mapping?filter_path=**.mappings._routing
# 检查是否必需
GET /<index>/_mapping?filter_path=**.mappings._routing.required
14. 搜索多个路由值 #
# 可以指定多个路由值
GET /<index>/_search?routing=value1,value2,value3
{
"query": {
"match_all": {}
}
}
15. 使用别名处理路由 #
# 创建包含路由值的别名
POST /_aliases
{
"actions": [
{
"add": {
"index": "<index>",
"alias": "<index>_alias",
"routing": "routing_value"
}
}
]
}
预防措施 #
- 在索引创建时明确路由要求
- 在客户端代码中配置默认路由
- 为父子关系使用正确的路由
- 在批量操作中包含路由值
- 文档化路由配置
- 使用有意义的路由值
- 监控路由缺失错误
- 实现客户端验证
- 使用映射中的路由路径
- 测试所有操作的配置





