UUID 的弹性搜索 Ngram 分词器性能
Elastic search Ngram tokenizer performance for UUID
我想对 UUID、reference_id 和 postal_code 进行部分过滤。对于 reference_id 和 postal_code,我知道它们的长度将小于 36。但是 UUID 的长度是 36 个字符。我正在考虑将 ngram 分词器设置为:
最小 ngram 1
最大 ngram 36
这会在速度和内存方面变得非常糟糕吗?有没有更好的方法来部分搜索 UUID?
例如,我有 7e222584-0818-49b0-875b-2774f4bf939b,我希望能够使用 9b0
搜索它
是的,这将创建大量令牌,实际上每个 UUID 36 + 35 + 34 + 33 + ... + 1 = (1 + 36) * (36/2) = 666 个令牌,这就是灰心。即使在创建 ngram 标记过滤器时,最小值和最大值之间的默认接受距离为 1,因此您必须在索引设置中覆盖它,这会给您第一个迹象表明它可能不是正确的做法。
您可能想尝试一下新的 wildcard
query field which might do a better job。
您可以轻松地比较这两种方法,方法是创建两个索引并在两者中索引相同数量(但相当大)的 UUID,然后比较它们的大小。
ngram 的第一个索引:
PUT uuid1
{
"settings": {
"index.max_ngram_diff": 36,
"analysis": {
"analyzer": {
"uuid": {
"tokenizer": "keyword",
"filter": [
"ngram"
]
}
},
"filter": {
"ngram": {
"type": "ngram",
"min_gram": 1,
"max_gram": 36
}
}
}
},
"mappings": {
"properties": {
"uuid": {
"type": "text",
"analyzer": "uuid",
"search_analyzer": "standard"
}
}
}
}
带通配符的第二个索引:
PUT uuid2
{
"mappings": {
"properties": {
"uuid": {
"type": "wildcard"
}
}
}
}
然后你在两者中索引相同的数据:
POST _bulk/_doc
{ "index": {"_index": "uuid1"}}
{ "uuid": "7e222584-0818-49b0-875b-2774f4bf939b"}
{ "index": {"_index": "uuid2"}}
{ "uuid": "7e222584-0818-49b0-875b-2774f4bf939b"}
最后你可以比较它们的大小,你可以看到 uuid
索引会比 uuid2
索引大。这里是 3 倍,但您可能希望索引更多数据以找出更好的比率:
GET _cat/shards/uuid*?v
index shard prirep state docs store ip node
uuid1 0 p STARTED 1 10.6kb 10.0.33.86 instance-0000000062
uuid2 0 p STARTED 1 3.5kb 10.0.12.26 instance-0000000042
利用 wildcard
在第二个索引上搜索可以像这样非常容易地完成,所以它很简单,就像您使用 ngrams 在索引上执行的 match
查询:
POST uuid2/_search
{
"query": {
"wildcard": {
"uuid": "*9b0*"
}
}
}
我想对 UUID、reference_id 和 postal_code 进行部分过滤。对于 reference_id 和 postal_code,我知道它们的长度将小于 36。但是 UUID 的长度是 36 个字符。我正在考虑将 ngram 分词器设置为:
最小 ngram 1
最大 ngram 36
这会在速度和内存方面变得非常糟糕吗?有没有更好的方法来部分搜索 UUID? 例如,我有 7e222584-0818-49b0-875b-2774f4bf939b,我希望能够使用 9b0
搜索它是的,这将创建大量令牌,实际上每个 UUID 36 + 35 + 34 + 33 + ... + 1 = (1 + 36) * (36/2) = 666 个令牌,这就是灰心。即使在创建 ngram 标记过滤器时,最小值和最大值之间的默认接受距离为 1,因此您必须在索引设置中覆盖它,这会给您第一个迹象表明它可能不是正确的做法。
您可能想尝试一下新的 wildcard
query field which might do a better job。
您可以轻松地比较这两种方法,方法是创建两个索引并在两者中索引相同数量(但相当大)的 UUID,然后比较它们的大小。
ngram 的第一个索引:
PUT uuid1
{
"settings": {
"index.max_ngram_diff": 36,
"analysis": {
"analyzer": {
"uuid": {
"tokenizer": "keyword",
"filter": [
"ngram"
]
}
},
"filter": {
"ngram": {
"type": "ngram",
"min_gram": 1,
"max_gram": 36
}
}
}
},
"mappings": {
"properties": {
"uuid": {
"type": "text",
"analyzer": "uuid",
"search_analyzer": "standard"
}
}
}
}
带通配符的第二个索引:
PUT uuid2
{
"mappings": {
"properties": {
"uuid": {
"type": "wildcard"
}
}
}
}
然后你在两者中索引相同的数据:
POST _bulk/_doc
{ "index": {"_index": "uuid1"}}
{ "uuid": "7e222584-0818-49b0-875b-2774f4bf939b"}
{ "index": {"_index": "uuid2"}}
{ "uuid": "7e222584-0818-49b0-875b-2774f4bf939b"}
最后你可以比较它们的大小,你可以看到 uuid
索引会比 uuid2
索引大。这里是 3 倍,但您可能希望索引更多数据以找出更好的比率:
GET _cat/shards/uuid*?v
index shard prirep state docs store ip node
uuid1 0 p STARTED 1 10.6kb 10.0.33.86 instance-0000000062
uuid2 0 p STARTED 1 3.5kb 10.0.12.26 instance-0000000042
利用 wildcard
在第二个索引上搜索可以像这样非常容易地完成,所以它很简单,就像您使用 ngrams 在索引上执行的 match
查询:
POST uuid2/_search
{
"query": {
"wildcard": {
"uuid": "*9b0*"
}
}
}