ElasticSearch 过滤别名创建 - 最佳实践
ElasticSearch Filtered Aliases Creation - Best Practice
我们计划使用这里提到的过滤别名 - https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
我们的输入数据将是一个流,流的每一行对应一个我们想要存储在 ES 中的对象。
每个对象都包含一个 'id',我们将其用于路由和过滤。
问题 -
我们如何以高效的方式创建别名和索引数据?
-- 我们是否索引所有数据,跟踪所有唯一的 'id's 并在最后创建过滤别名?或者
-- 对于每个对象,检查是否存在 'id' 的别名;如果它不创建一个?
我倾向于第一种方法。与第二种方法相比,它是否可取且性能良好?
TIA。
根据我们上面的讨论并浏览了您发布的博客文章后,我非常肯定您的情况根本不需要别名,路由密钥就足够了。同样,仅因为您只有一个索引,如果您有多个索引,这将不再适用!
您只需指定在索引文档时使用的路由键。在 ES 2.0 之前,您可以将 _routing
field 用于该目的,即使它在 ES 1.5 中已被弃用,但在您的情况下它可以满足您的目的。
{
"customer" : {
"_routing" : {
"required" : true,
"path" : "customer_id" <----- the field you use as the routing key
},
"properties": { ... }
}
}
然后在搜索时,除了客户 ID 过滤器之外,您只需在搜索 URL 中指定 &routing=<customer_id>
(因为给定的分片可以为不同的客户托管文档)。您的搜索将直接转到由给定路由键标识的分片,因此仅检索来自指定客户的数据。
为此使用过滤别名不会带来任何好处,因为您在别名定义中包含的过滤器和路由键不会产生任何额外的作用,因为检索到的文档已经 "filtered"(有点)路由键。这比尝试检测(在每个要索引的新文档上)是否存在别名并在不存在时创建别名要容易得多。
更新:
现在,如果您绝对 have/want 创建过滤别名,则性能更高的方法将是您提到的第一个方法:
- 首先索引你的日常数据
- 然后 运行 在
customer_id
字段上进行 terms
聚合,size
足够高(即高于字段的基数,在您的字段中约为 100案例)以确保您捕获所有唯一的客户 ID 以创建您的别名
- 遍历所有存储桶以检索所有唯一客户 ID
- 在 one shot 中创建所有别名,每个
customer_id
使用一个 action
curl -XPOST 'http://localhost:9200/_aliases' -d '{
"actions" : [
{
"add" : {
"index" : "customers",
"alias" : "alias_cid1",
"routing" : "cid1",
"filter" : { "term" : { "customer_id" : "cid1" } }
}
},
{
"add" : {
"index" : "customers",
"alias" : "alias_cid2",
"routing" : "cid2",
"filter" : { "term" : { "customer_id" : "cid2" } }
}
},
{
"add" : {
"index" : "customers",
"alias" : "alias_cid3",
"routing" : "cid3",
"filter" : { "term" : { "customer_id" : "cid3" } }
}
},
...
]
}'
请注意,如果别名已经存在,您不必担心,整个命令不会失败并默默地忽略现有别名。
当此命令具有 运行 时,您将在唯一索引上拥有所有别名,并使用过滤器和路由键正确配置。
我们计划使用这里提到的过滤别名 - https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
我们的输入数据将是一个流,流的每一行对应一个我们想要存储在 ES 中的对象。
每个对象都包含一个 'id',我们将其用于路由和过滤。
问题 - 我们如何以高效的方式创建别名和索引数据?
-- 我们是否索引所有数据,跟踪所有唯一的 'id's 并在最后创建过滤别名?或者
-- 对于每个对象,检查是否存在 'id' 的别名;如果它不创建一个?
我倾向于第一种方法。与第二种方法相比,它是否可取且性能良好?
TIA。
根据我们上面的讨论并浏览了您发布的博客文章后,我非常肯定您的情况根本不需要别名,路由密钥就足够了。同样,仅因为您只有一个索引,如果您有多个索引,这将不再适用!
您只需指定在索引文档时使用的路由键。在 ES 2.0 之前,您可以将 _routing
field 用于该目的,即使它在 ES 1.5 中已被弃用,但在您的情况下它可以满足您的目的。
{
"customer" : {
"_routing" : {
"required" : true,
"path" : "customer_id" <----- the field you use as the routing key
},
"properties": { ... }
}
}
然后在搜索时,除了客户 ID 过滤器之外,您只需在搜索 URL 中指定 &routing=<customer_id>
(因为给定的分片可以为不同的客户托管文档)。您的搜索将直接转到由给定路由键标识的分片,因此仅检索来自指定客户的数据。
为此使用过滤别名不会带来任何好处,因为您在别名定义中包含的过滤器和路由键不会产生任何额外的作用,因为检索到的文档已经 "filtered"(有点)路由键。这比尝试检测(在每个要索引的新文档上)是否存在别名并在不存在时创建别名要容易得多。
更新:
现在,如果您绝对 have/want 创建过滤别名,则性能更高的方法将是您提到的第一个方法:
- 首先索引你的日常数据
- 然后 运行 在
customer_id
字段上进行terms
聚合,size
足够高(即高于字段的基数,在您的字段中约为 100案例)以确保您捕获所有唯一的客户 ID 以创建您的别名 - 遍历所有存储桶以检索所有唯一客户 ID
- 在 one shot 中创建所有别名,每个
customer_id
使用一个action
curl -XPOST 'http://localhost:9200/_aliases' -d '{ "actions" : [ { "add" : { "index" : "customers", "alias" : "alias_cid1", "routing" : "cid1", "filter" : { "term" : { "customer_id" : "cid1" } } } }, { "add" : { "index" : "customers", "alias" : "alias_cid2", "routing" : "cid2", "filter" : { "term" : { "customer_id" : "cid2" } } } }, { "add" : { "index" : "customers", "alias" : "alias_cid3", "routing" : "cid3", "filter" : { "term" : { "customer_id" : "cid3" } } } }, ... ] }'
请注意,如果别名已经存在,您不必担心,整个命令不会失败并默默地忽略现有别名。
当此命令具有 运行 时,您将在唯一索引上拥有所有别名,并使用过滤器和路由键正确配置。