multi_match 和 bool_prefix 类型的 Elasticsearch 模糊性

Elasticsearch fuzziness with multi_match and bool_prefix type

我有一组 search_as_you_type_fields 需要搜索。这是我的映射

"mappings" : {
      "properties" : {
        "description" : {
          "type" : "search_as_you_type",
          "doc_values" : false,
          "max_shingle_size" : 3
        },
        "questions" : {
          "properties" : {
            "content" : {
              "type" : "search_as_you_type",
              "doc_values" : false,
              "max_shingle_size" : 3
            },
            "tags" : {
              "type" : "text",
              "fields" : {
                "keyword" : {
                  "type" : "keyword"
                }
              }
            }
          }
        },
      
        "title" : {
          "type" : "search_as_you_type",
          "doc_values" : false,
          "max_shingle_size" : 3
        },
      }
    }

我正在使用 bool_prefix 类型的 multi_match 查询。

"query": {
    "multi_match": {
      "query": "triangle", 
      "type": "bool_prefix",
       "fields": [
           "title",
           "title._2gram",
           "title._3gram",
           "description",
           "description._2gram",
           "description._3gram",
           "questions.content",
           "questions.content._2gram",
           "questions.content._3gram",
           "questions.tags",
           "questions.tags._2gram",
           "questions.tags._3gram"
       ]
    }
  }

到目前为止工作正常。现在我想添加一个错字容忍度,这在 ES 中是模糊的。但是,看起来 bool_prefix 与此有一些冲突。因此,如果我修改我的查询并添加“fuzziness”:“AUTO”并在单词“triangle”->“triangld”中出错,它不会得到任何结果。

但是,如果我要查找短语“直角三角形”,我会有一些不同的行为:

  1. 即使没有拼写错误,我也得到了更多“模糊”的结果:“AUTO”(1759 对 1267)
  2. 如果我在二维词“right triangdd”中添加错字,它似乎可以工作,但看起来它现在推送包含“right”而不是“triangle”的结果(“The Bill of Rights”,“正当程序和隐私权”等)在前面。
  3. 如果我在第一个词(“直角三角形”)或两个词(“直角三角形”)中打错字,结果似乎还不错。所以这可能是唯一正确的行为。

我看过几篇文章甚至 GitHub 问题,模糊性不能以正确的方式使用 bool_prefix 的 multi_match 查询,但是我不能找到解决方法。我试过更改查询类型,但看起来 bool_prefix 是唯一支持您键入时搜索的类型,我需要在用户开始键入内容时获取搜索结果。

因为我从后端发出来自 ES 的所有请求我还可以做的是操作查询字符串以在需要时构建不同的搜索查询类型。例如,对于单字搜索,使用一种类型用于多用途另一种。但我基本上需要保持当前的行为。

我也试过在字符串上附加一个符号“~”或“~1[2]”,这似乎是另一种指定模糊性的方式,但结果相当不清楚并且性能(搜索速度)好像更糟了。

我的问题是:

  1. 如何实现 1 个词搜索的模糊性?这样查询“triangld”returns 包含“triangle”等的文档
  2. 当查询的第 2 个(最后一个?)字出现拼写错误时,如何才能获得正确的搜索结果?就像我上面提到的那样有效,但请参阅上面的第 2 点
  3. 为什么只添加模糊性(参见第 1 页)returns 即使短语正确也有更多结果?
  4. 我的分析仪等有什么需要改变的吗?

因此,为了实现所需的行为,我们执行了以下操作:

  1. 将查询类型更改为“query_string”
  2. 在后端添加了查询字符串预处理。我们用白色 spaces 拆分查询字符串,如果每个单词的长度分别超过 4 个字符或 8 个字符,则向每个单词添加“~1”或“~2”。 ~ 是 ES 中的模糊语法。但是,直到用户键入白色 space 后,我们才会将其添加到当前键入的单词中。例如,用户键入 [t, tr, tri, ... triangle] => 不模糊,但输入“triangle” => “triangle~2”。这是因为最后一个词有模糊性会有意想不到的结果
  3. 我们还从搜索字段中删除了所有 ngram 字段,因为我们得到了相同的结果,但性能更好一些。
  4. 向查询添加了“default_operator”:“AND”以包含短语查询的一个字段的结果