我想将文档索引到特定的 ElasticSearch 分片。
我知道我可以配置 ES 来查看一个字段,然后根据该字段将其发送到特定的分片。
我不想那样做。我只想说: 1) 好的,我决定本周将所有文档导入 Shard 1,因为我喜欢它。
我知道有一种方法可以将查询发送到特定的分片,但是导入呢?
我怎样才能做到这一点?
我想将文档索引到特定的 ElasticSearch 分片。
我知道我可以配置 ES 来查看一个字段,然后根据该字段将其发送到特定的分片。
我不想那样做。我只想说: 1) 好的,我决定本周将所有文档导入 Shard 1,因为我喜欢它。
我知道有一种方法可以将查询发送到特定的分片,但是导入呢?
我怎样才能做到这一点?
如果你想完全控制分片,你应该使用多个索引和一个分片,而不是一个索引和多个分片。这样,您将能够决定数据将转到哪个索引(和分片,因为每个索引只有一个分片)。您还可以创建一个别名,将所有此类索引组合成一个别名,因此您不必担心在搜索过程中列出所有索引。
从性能的角度来看,使用 10 个分片搜索单个索引与使用单个分片搜索 10 个索引之间几乎没有区别。在这两种情况下,您都将搜索 10 个分片。在这种情况下您应该担心的一件事是保持映射兼容。您可能不希望在一个索引中将字段索引为字符串,而在另一个索引中索引为整数。
我确信您已经解决了您的问题或找到了另一个解决方案,但我在项目中遇到了类似的问题,我想发布我们为将文档索引到特定分片所做的工作。
_routing
您可以通过Elasticsearch 的字段来实现这一点,方法是使用 Elasticsearch 给定的公式计算分片数:
shard_num = hash(_routing) % num_primary_shards
假设您想将一个文档分配给 2 号分片,并且当分片编号为 10 时,您必须给出路由名称,同时从其哈希值和分片编号中获取模数。为此,您必须找到一个路由名称,为了在代码中进行解释,我将在 Java 中给出一个示例,以查找具有特定路由名称的分片号:
for (int i = 0; i < 5; i++) {
String routing = "tenant"+i;
final int numberOfShard = 30;
final int shard = routing.hashCode() % numberOfShard;
System.out.println("Routing: " + routing + " - shard number: " + shard);
}
输出:
Routing: tenant0 - shard number: -2
Routing: tenant1 - shard number: -1
Routing: tenant2 - shard number: 0
Routing: tenant3 - shard number: -29
Routing: tenant4 - shard number: -28
您必须生成一个字符串,将其哈希值和分片数取模,得出您想要的分片数。从上面的输出中,tenant0
路由名称导致shard number 2
.
作为一个完整的示例,我想演示使用路由名称进行索引:
假设我们创建“课程”索引并设置所需的路由:
PUT http://localhost:9200/course
{
"settings": {
"number_of_shards": 30
},
"mappings": {
"_routing": {
"required": true
}
}
}
然后你索引一个这样的文档:
PUT http://localhost:9200/course_index/_doc/1?routing=tenant0&refresh=true
{
"id": 1,
"title": "Data Security course in Lidl",
"description": "The course teaches our core Data Security measurements here in Lidle. As new regulations are out, ....",
"text": "Text of the couse goes here",
"created_date": 152625632,
"last_date": 152625632,
"expiration_date": null,
"domain_id": 10,
"language_id": 2
}
在我们的案例中,我们有一个多租户软件,其中大约 100 个租户(组织)在 Elasticsearch 中共享相同的索引,我们必须确保一个租户永远无法看到其他租户的数据的数据安全性。我们的解决方案是为所有租户创建一个包含 100 个分片的索引,并通过为每个租户找到一个路由名称来为每个租户分配一个分片。正如您在上面的索引映射示例中所见,路由设置为“必需”,每当您将 CRUD 操作发送到 Elasticsearch 时,您都必须定义路由,否则 Elasticsearch 将抛出routing_missing_exception