Elasticsearch - multi_match和短查询

时间:2017-08-07 05:33:43

标签: elasticsearch

我有这样的查询(我已经删除了排序部分,因为它并不重要):

GET _search
{
  "query": {
    "multi_match": {
        "query":  "somethi",
        "fields": [ "title", "content"],
        "fuzziness" : "AUTO",
        "prefix_length" : 0
    }
  }
}

运行时,我得到的结果如下:

"hits": [
  {
    "_index": "test_index",
    "_type": "article",
    "_id": "2",
    "_score": 0.083934024,
    "_source": {
      "title": "Matching something abc",
      "content": "This is a piece of content",
      "categories": [
        {
          "name": "B",
          "weight": 4
        }
      ]
    },
    "sort": [
      4,
      0.083934024,
      "article#2"
    ]
  },
  {
    "_index": "test_index",
    "_type": "article",
    "_id": "3",
    "_score": 0.18436861,
    "_source": {
      "title": "Matching something abc",
      "content": "This is a piece of content containing something",
      "categories": [
        {
          "name": "C",
          "weight": 3
        }
      ]
    },
    "sort": [
      3,
      0.18436861,
      "article#3"
    ]
  },
  ...

获得预期没什么问题。但是我注意到,我从查询中删除了一个字母而不是someth,Elasticsearch不会返回任何结果。

这对我来说很奇怪。似乎multi_match正在进行部分匹配,但它以某种方式需要使用最少x个字符。同样,如果我尝试查询例如omethin,我会得到结果,但只使用omethi我不会得到任何结果。

是否有任何设置来设置查询中的最小字符数,或者我可能需要重写我的查询以实现我想要的?我想在多个字段上运行匹配(在上面的标题和内容字段查询中),这将允许部分匹配与模糊。

1 个答案:

答案 0 :(得分:1)

您会收到此行为,因为您设置了"fuzziness": "AUTO"参数,这意味着在一个超过5个字符的单词中,错误地放置最多两个字符是可以接受的。通常,fuzziness parameter告诉elasticsearch查找最多包含两个更改的所有术语,其中更改是单个字符的插入,删除或替换。由于模糊,不可能有两个以上的变化。

如果您需要能够使用部分匹配进行搜索,可以尝试使用Edge NGram analyzer配置索引,并将其设置为titlecontent字段。您可以轻松测试其工作原理:

使用以下映射创建na索引:

PUT http://127.0.0.1:9200/test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "edge_ngram_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  }
}

运行此查询:

curl -X POST \
  'http://127.0.0.1:9200/test/_analyze?pretty=true' \
  -d '{
  "analyzer" : "edge_ngram_analyzer",
  "text" : ["something"]
}'

结果你会得到:

{
    "tokens": [
        {
            "token": "so",
            ...
        },
        {
            "token": "som",
            ...
        },
        {
            "token": "some",
            ...
        },
        {
            "token": "somet",
            ...
        },
        {
            "token": "someth",
            ...
        },
        {
            "token": "somethi",
            ...
        },
        {
            "token": "somethin",
            ...
        },
        {
            "token": "something",
            ...
        }
    ]
}

这些是您在edge_ngram_analyzer搜索期间获得的令牌。使用min_grammax_gram,您可以配置克的最小/最大字符长度。

如果您需要使用omething等处理案例(开头缺少字母),请尝试使用NGram analyzer