【问题标题】:Elastic search Ngram tokenizer performance for UUIDUUID 的弹性搜索 Ngram 标记器性能
【发布时间】:2021-06-22 20:24:15
【问题描述】:

我想对 UUID、reference_id 和 postal_code 进行部分过滤。对于 reference_id 和 postal_code,我知道它们会比长度 36 短。但 UUID 是 36 个字符长。我正在考虑将 ngram 标记器设置为:

分钟 1

最大 ngram 36

这在速度和内存方面会变得非常糟糕吗?有没有更好的方法来部分搜索 UUID? 例如,我有 7e222584-0818-49b0-875b-2774f4bf939b,我希望能够使用 9b0 搜索它

【问题讨论】:

  • 使用a查询UUID的随机性太高,应该降低

标签: elasticsearch filter wildcard uuid n-gram


【解决方案1】:

是的,这将创建大量的令牌,实际上是 36 + 35 + 34 + 33 + ... + 1 = (1 + 36) * (36/2) = 每个 UUID 的 666 个令牌,这是不鼓励的。即使在创建 ngram 标记过滤器时,默认接受的 min 和 max 之间的距离也是 1,因此您必须在索引设置中覆盖它,这会给您第一个指示,表明它可能不是正确的做法。

您可能想尝试一下新的wildcard query field 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 在第二个索引上搜索,可以像这样非常容易地完成,所以它就像一个简单的 match 查询一样,您可以使用 ngrams 在索引上执行:

POST uuid2/_search
{
  "query": {
    "wildcard": {
      "uuid": "*9b0*"
    }
  }
}

【讨论】:

  • 我知道通配符字段类型,但据我了解,将 * 放在性能术语的前面和结尾是不好的。也许我应该区分?对于邮政编码和reference_id,我可以使用ngram,但对于UUID,我应该使用通配符?
  • 这不仅与通配符查询有关,使用前导 * 确实不好,而且还与专门为此目的创建的 new wildcard field 有关。因此,通配符字段+查询组合最适合您的用例
  • 所以如果我使用查询词 *9b0* 作为通配符字段,你的意思是没问题?
  • 请点击我两次引用的链接 :-)
猜你喜欢
  • 1970-01-01
  • 2017-12-23
  • 2020-08-28
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-27
  • 1970-01-01
相关资源
最近更新 更多