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*"
    }
  }
}