_routing 字段

编辑

文档使用以下公式路由到索引中的特定分片

routing_factor = num_routing_shards / num_primary_shards
shard_num = (hash(_routing) % num_routing_shards) / routing_factor

num_routing_shardsindex.number_of_routing_shards 索引设置的值。num_primary_shardsindex.number_of_shards 索引设置的值。

默认的 _routing 值是文档的 _id。可以通过为每个文档指定自定义的 routing 值来实现自定义路由模式。例如:

resp = client.index(
    index="my-index-000001",
    id="1",
    routing="user1",
    refresh=True,
    document={
        "title": "This is a document"
    },
)
print(resp)

resp1 = client.get(
    index="my-index-000001",
    id="1",
    routing="user1",
)
print(resp1)
response = client.index(
  index: 'my-index-000001',
  id: 1,
  routing: 'user1',
  refresh: true,
  body: {
    title: 'This is a document'
  }
)
puts response

response = client.get(
  index: 'my-index-000001',
  id: 1,
  routing: 'user1'
)
puts response
const response = await client.index({
  index: "my-index-000001",
  id: 1,
  routing: "user1",
  refresh: "true",
  document: {
    title: "This is a document",
  },
});
console.log(response);

const response1 = await client.get({
  index: "my-index-000001",
  id: 1,
  routing: "user1",
});
console.log(response1);
PUT my-index-000001/_doc/1?routing=user1&refresh=true 
{
  "title": "This is a document"
}

GET my-index-000001/_doc/1?routing=user1 

此文档使用 user1 作为其路由值,而不是其 ID。

获取删除更新文档时,需要提供相同的 routing 值。

在查询中可以访问 _routing 字段的值

resp = client.search(
    index="my-index-000001",
    query={
        "terms": {
            "_routing": [
                "user1"
            ]
        }
    },
)
print(resp)
response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      terms: {
        _routing: [
          'user1'
        ]
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my-index-000001",
  query: {
    terms: {
      _routing: ["user1"],
    },
  },
});
console.log(response);
GET my-index-000001/_search
{
  "query": {
    "terms": {
      "_routing": [ "user1" ] 
    }
  }
}

_routing 字段上进行查询(另请参阅 ids 查询

数据流不支持自定义路由,除非它们是在模板中启用了 allow_custom_routing 设置的情况下创建的。

使用自定义路由进行搜索

编辑

自定义路由可以减少搜索的影响。搜索请求不必扇出到索引中的所有分片,而是可以将请求仅发送到与特定路由值(或多个值)匹配的分片

resp = client.search(
    index="my-index-000001",
    routing="user1,user2",
    query={
        "match": {
            "title": "document"
        }
    },
)
print(resp)
response = client.search(
  index: 'my-index-000001',
  routing: 'user1,user2',
  body: {
    query: {
      match: {
        title: 'document'
      }
    }
  }
)
puts response
const response = await client.search({
  index: "my-index-000001",
  routing: "user1,user2",
  query: {
    match: {
      title: "document",
    },
  },
});
console.log(response);
GET my-index-000001/_search?routing=user1,user2 
{
  "query": {
    "match": {
      "title": "document"
    }
  }
}

此搜索请求将仅在与 user1user2 路由值关联的分片上执行。

使路由值成为必需

编辑

使用自定义路由时,在索引获取删除更新文档时,提供路由值非常重要。

忘记路由值可能导致文档在多个分片上建立索引。作为一种安全措施,可以配置 _routing 字段,以使所有 CRUD 操作都必须使用自定义的 routing

resp = client.indices.create(
    index="my-index-000002",
    mappings={
        "_routing": {
            "required": True
        }
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000002",
    id="1",
    document={
        "text": "No routing value provided"
    },
)
print(resp1)
response = client.indices.create(
  index: 'my-index-000002',
  body: {
    mappings: {
      _routing: {
        required: true
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000002',
  id: 1,
  body: {
    text: 'No routing value provided'
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000002",
  mappings: {
    _routing: {
      required: true,
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000002",
  id: 1,
  document: {
    text: "No routing value provided",
  },
});
console.log(response1);
PUT my-index-000002
{
  "mappings": {
    "_routing": {
      "required": true 
    }
  }
}

PUT my-index-000002/_doc/1 
{
  "text": "No routing value provided"
}

所有文档都需要路由。

此索引请求会抛出 routing_missing_exception

自定义路由的唯一 ID

编辑

在索引指定了自定义 _routing 的文档时,不能保证 _id 在索引的所有分片中都是唯一的。实际上,如果使用不同的 _routing 值进行索引,则具有相同 _id 的文档可能会最终出现在不同的分片上。

用户有责任确保 ID 在整个索引中是唯一的。

路由到索引分区

编辑

可以配置索引,使自定义路由值将转到分片的子集,而不是单个分片。这有助于减轻最终导致集群不平衡的风险,同时仍然减少了搜索的影响。

这是通过在索引创建时提供索引级别的设置 index.routing_partition_size 来完成的。随着分区大小的增加,数据分布将变得更加均匀,但代价是每次请求必须搜索更多的分片。

当存在此设置时,用于计算分片的公式变为

routing_value = hash(_routing) + hash(_id) % routing_partition_size
shard_num = (routing_value % num_routing_shards) / routing_factor

也就是说,_routing 字段用于计算索引中的一组分片,然后使用 _id 来选择该组中的分片。

要启用此功能,index.routing_partition_size 应具有大于 1 且小于 index.number_of_shards 的值。

启用后,分区索引将具有以下限制

  • 无法在其内部创建具有 join 字段关系的映射。
  • 索引中的所有映射都必须将 _routing 字段标记为必需。