弹性搜索中的自动完成匹配

Autocomplete matching in Elastic Search

所以我在弹性搜索中有一个 identifier 字符串字段,其中包含 D123M1T23 等值

我正在尝试在该字段的搜索中构建自动完成功能,以便 D12 的查询可能匹配 D12D120D121、... , D1210

目前我已经构建了一个自定义的边缘 ngram 过滤器和分析器:

"filter": {
  "autocomplete_filter": {
    "type": "edgeNGram",
    "min_gram": 2,
    "max_gram": 10
  }
}

"analyzer": {
  "autocomplete": {
      "type": "custom",
      "tokenizer": "whitespace",
      "filter": {"lowercase", "autocomplete_filter"}
  }
}

在我的映射中,当 indexing:

时,我在 identifier 字段上使用它
"identifier": {
  "type": "string",
  "analyzer": "autocomplete",
  "search_analyzer": "standard"
}

这意味着为 D1234 编制索引的 ngram 是 D1D12D123D1234

要查询这个我是这样做的:

"query": {
  "bool": {
    "should": {
      "match": {
        "identifier": {
          "query": "D12",
          "fuzziness": 0
        }
      }
    }
  }
}

这个returns结果从最长到最短,所以D12出现在结果的末尾。我将如何确保尽可能短的标识符具有最高的相关性分数?

我的猜测是 D12 查询像这样匹配 ngrams:[{D12}, {D12}3, {D12}34] 并且弹性搜索去 "Oh great, 3 matches!" 而不是 [{D12}] D12 结果会给出。

我想一个解决方案可能不会部分匹配那些 ngram,因此弹性搜索会看到两个结果的 [{D12}] 但排名 D12 高于 D1234 因为它匹配了 1/2 ngram 而不是 1/4。我不确定如何配置弹性搜索来给出这个结果。

如有任何帮助,我们将不胜感激。

您可以使用 script based sorting 执行此操作,但首先您需要将 identifier 字段映射为 multi-fields,就像这样

"identifier": {
    "type": "string",
    "analyzer": "autocomplete",
    "search_analyzer": "standard",
    "fields": {
        "raw": {
            "type": "string",
            "index": "not_analyzed"
        }
    }
}

您需要这样做,因为如果您直接在 identifiersort 那么您将得到相同的结果,因为它们都将具有 2 个字母标记 由于 edge ngram filter。之后这会给你想要的结果

{
  "query": {
    "bool": {
      "should": {
        "match": {
          "identifier": {
            "query": "D12",
            "fuzziness": 0
          }
        }
      }
    }
  },
  "sort": {
    "_script": {
      "script": "doc['identifier.raw'].value.length()",
      "order": "asc",
      "type": "number"
    }
  }
}

希望对您有所帮助!!