【问题标题】:Elasticsearch: why exact match has lower score than partial matchElasticsearch:为什么完全匹配的分数低于部分匹配
【发布时间】:2020-03-04 09:51:29
【问题描述】:

我的问题

我搜索单词form,但精确匹配的单词form 不是结果中的第一个。有没有办法解决这个问题?

我的搜索查询

{
  "query": {
    "match": {
      "word": "form"
    }
  }
}

结果

word             score
--------------------------
formulation      10.864353
formaldehyde     10.864353
formless         10.864353
formal   10.84412
formerly         10.84412
forma    10.84412
formation        10.574185
formula          10.574185
formulate        10.574185
format   10.574185
formally         10.574185
form     10.254687
former   10.254687
formidable       10.254687
formality        10.254687
formative        10.254687
ill-formed       10.054999
in form          10.035862
pro forma        9.492243

POST my_index/_analyze

搜索中的单词form只有一个标记form

在索引中,form 标记为 ["f", "fo", "for", "form"]; formulation 标记是 ["f", "fo", ..., "formulatio", "formulation"]。

我的配置

过滤器

        "edgengram_filter": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 20
        }

分析仪

      "analyzer": {
        "abc_vocab_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "keyword_repeat",
            "lowercase",
            "asciifolding",
            "edgengram_filter",
            "unique"
          ]
        },
        "abc_vocab_search_analyzer": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "keyword_repeat",
            "lowercase",
            "asciifolding",
            "unique"
          ]
        }
      }

映射

        "word": {
          "type": "text",
          "analyzer": "abc_vocab_analyzer",
          "search_analyzer": "abc_vocab_search_analyzer"
        }

【问题讨论】:

  • 我在下面提供了一个答案,但我很好奇为什么你的 min-grammax-gram 有如此巨大的差异。如果您可以提供有关您的用例的更多信息,这将很有帮助,因为我认为不需要将 min-gram 设置为 1 或 2,这只会消耗巨大的空间而不会提供任何优势。 max-ngram 设置为 20 也是如此。也许它取决于您的域,但如果您决定将 min 和 max ngram 设置得那么高,请对您的索引大小进行彻底分析。

标签: elasticsearch elasticsearch-5 elasticsearch-dsl elasticsearch-6


【解决方案1】:

您以您看到的方式获得结果,因为您已经实现了edge-ngram 过滤器并且form 是与其相似的单词的子字符串。基本上在倒排索引中,它还会存储包含formulationformal 等的文档ID。

因此,您的相关性也会以这种方式计算。您可以参考this 链接,我特别建议您浏览Default SimilarityBM25 部分。尽管目前的默认相似度为BM25,但该链接将帮助您了解评分的工作原理。

您需要创建另一个可以在 should 子句中应用的同级字段。您可以继续使用Term Query 创建keyword 子字段,但您需要注意区分大小写。

相反,正如@Val 所述,您可以使用标准分析器创建text 字段的兄弟。

映射:

   {
    "word":{
      "type": "text",
      "analyzer": "abc_vocab_analyzer",
      "search_analyzer": "abc_vocab_search_analyzer"
      "fields":{
        "standard":{
          "type": "text"
        }
      }
    }
  }

查询:

POST <your_index_name>/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "word": "form"
          }
        }
      ],
      "should": [                          <---- Note this
        {
          "match": {
            "word.standard": "form"
          }
        }
      ]
    }
  }
}

如果这有帮助,请告诉我!

【讨论】:

  • 看起来有点矫枉过正,如果分析器配置正确,ES默认给出最高分来精确匹配,请看我的回答。
  • @OpsterElasticsearchNinja 这很奇怪,我在 ES 5.x 版本上进行了测试并遇到了同样的问题。我希望你已经在 ES 7.x 版本上进行了测试。
  • 是的,我在最新的 7.6 上测试过,你能用我的例子看看它在 5.x 中是否给出错误的结果吗?
  • 子字段方法是正确的。但是,关键字字段/术语查询组合会使查询区分大小写,这并不理想。为了缓解这种情况,我建议使用标准分析器的文本字段,以便您可以在 should 约束中进行匹配查询。
  • @Amit,这是我做的第一件事,它给了我错误的结果!!
【解决方案2】:

因为你这个字段的类型是文本,这意味着 ES 会在这个字段上做全文搜索分析。而ES搜索的过程就是寻找与你给出的词最相似的结果。
要准确搜索“form”这个词,请将你的搜索方式改为match_phrase
另外,你也可以阅读下面的文章来学习有关不同 ES 搜索方法的更多信息: https://www.cnblogs.com/yjf512/p/4897294.html https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html

【讨论】:

  • match_phrase 具有相同的结果。我只搜索一个词,使用自己的分析器和search_analyzer,有什么建议吗?
  • 一种选择是将此字段重新键入为术语,在这种情况下,将在此字段上禁用全文搜索。之后,您可以使用 termQuery 来获取您想要的确切单词。但是,如果此字段在全文上下文中被搜索的可能性很高,则这种方式可能会影响您自己的业务。
【解决方案3】:

在您的自定义分析器中看起来有些问题,我创建了我的自定义 autocomplete 分析器,它使用 edge_ngramlowercase 过滤器,它适用于您的查询,返回我完全匹配的顶部这就是 Elasticsearch 的工作原理,完全匹配总是有更高的分数。,因此无需显式创建另一个字段并提升它,因为 Elasticsearch 默认会提升令牌匹配的完全匹配。

索引定义

{
  "settings": {
    "analysis": {
      "filter": {
        "autocomplete_filter": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 10
        }
      },
      "analyzer": {
        "autocomplete": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "autocomplete_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "autocomplete", 
        "search_analyzer": "standard" 
      }
    }
  }
}

索引几个文档

{
   "title" : "formless"
}

{
   "title" : "form"
}

{
   "title" : "formulation"
}

在问题中提供的title 字段上搜索查询

{
  "query": {
    "match": {
      "title": "form"
    }
  }
}

完全匹配的搜索结果得分最高

"hits": [
         {
            "_index": "so-60523240-score",
            "_type": "_doc",
            "_id": "1",
            "_score": 0.16410133,
            "_source": {
               "title": "form"
            }
         },
         {
            "_index": "so-60523240-score",
            "_type": "_doc",
            "_id": "2",
            "_score": 0.16410133,
            "_source": {
               "title": "formulation"
            }
         },
         {
            "_index": "so-60523240-score",
            "_type": "_doc",
            "_id": "3",
            "_score": 0.16410133,
            "_source": {
               "title": "formaldehyde"
            }
         },
         {
            "_index": "so-60523240-score",
            "_type": "_doc",
            "_id": "4",
            "_score": 0.16410133,
            "_source": {
               "title": "formless"
            }
         }
      ]

【讨论】:

    猜你喜欢
    • 2016-06-23
    • 2012-03-26
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 2019-04-03
    相关资源
    最近更新 更多