【问题标题】:Elasticsearch - Document better score when more words matchingElasticsearch - 当更多单词匹配时记录更好的分数
【发布时间】:2018-12-18 14:02:40
【问题描述】:

我有一个问题,希望有人可以帮助我。

我有一个使用匹配查询进行搜索的简单示例

"query": {
    "match": {
        "filterValues": "ordner ohne griffloch"
    }
}

我正好得到两个命中:

"hits" : [
  {
    "_index" : "filters",
    "_type" : "filter",
    "_id" : "F-114150068-1170182",
    "_score" : 5.420828,
    "_source" : {
      "filterValues" : [
        "Ja",
        "Griffloch vorhanden",
        "Griffloch",
        "mit Griffloch"
      ]
    },
    "highlight" : {
      "filterValues" : [
        "<em>Griffloch</em>"
      ]
    }
  },
  {
    "_index" : "filters",
    "_type" : "filter",
    "_id" : "F-114150069-1170182",
    "_score" : 4.452639,
    "_source" : {
      "filterValues" : [
        "ohne Griffloch",
        "kein Griffloch",
        "Nein"
      ]
    },
    "highlight" : {
      "filterValues" : [
        "<em>ohne Griffloch</em>"
      ]
    }
  }
]

我的问题是:我想找到第二个命中“ohne Griffloch”作为第一个(更好的分数),因为它匹配更多的单词。但我发现第一个得分更高,我想是因为它包含更多“Griffloch”。

我不能使用术语查询,因为当查询包含其他单词(此处为:“ordner”)时,我将找不到任何内容,因为它与任何内容都不完全匹配。

有什么想法吗?

谢谢!

有关索引配置的信息:

"settings": {
    "analysis": {
      "analyzer": {
        "default": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": [
            "lowercase"
          ]
        },
        "lowercase_shingle": {
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "my_shingle"
          ]
        }
      },
      "filter": {
        "my_shingle": {
          "type": "shingle",
          "min_shingle_size": 2,
          "max_shingle_size": 4
        }
      }
    }
  },
  "mappings": {
    "filter": {
      "properties": {
        "filterValueId": {
          "type": "long"
        },
        "filterValues": {
          "type": "text",
          "position_increment_gap": 100,
          "analyzer": "default",
          "search_analyzer": "lowercase_shingle"
        },
        "categoryId": {
          "type": "long"
        }
      }
    }
  }

【问题讨论】:

  • 请分享您的完整query 结构
  • 您希望采用哪种结构?我有我输入的所有内容,除了我删除的字段的突出显示。

标签: elasticsearch


【解决方案1】:

您应该在查询中添加短语匹配的提升。因此,在多个 filterValues 之一中找到所有查询词的文档将自然得到提升。

但是你需要注意这个怪癖(see here, official doc

我不知道怎么做(也许力在你身上),但你的映射对于 position_increment_gap 已经正确,但你应该删除设置

search_analyzer": "lowercase_shingle"

因为在您的上下文中似乎有点奇怪。

然后我们添加匹配短语的提升

{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "filterValues": "ordner ohne griffloch"
                    }
                }
            ],
            should: [
              {
                "match_phrase": {
                        "filterValues": {
                          "query": "ordner ohne griffloch",
                          "slop": 10 
                        }

                    }
                }
            ]
        }
    }
}

希望它有效!

评论后编辑:

如果您更改映射以在索引时使用 shingle_analyzer 添加子字段

"mappings": {
    "filter": {
      "properties": {
        "filterValueId": {
          "type": "long"
        },
        "filterValues": {
          "type": "text",
          "position_increment_gap": 100,
          "analyzer": "default",
          "search_analyzer": "lowercase_shingle",
          "fields": {
              "shingled": {
                   "type": "text",
                   "analyzer": "lowercase_shingle",
              }
          }
        },
        "categoryId": {
          "type": "long"
        }
      }
    }
  }

然后您可以使用此查询在 shingled 子字段上添加提升

{
        "query": {
            "bool": {
                "must": [
                    {
                        "match": {
                            "filterValues": "ordner ohne griffloch"
                        }
                    }
                ],
                should: [
                  {
                    "match": {
                            "filterValues.shingled": "ordner ohne griffloch" 
                        }
                    }
                ]
            }
        }
    }

它将在您的示例中提升第二个文档而不是第一个文档

【讨论】:

  • 感谢您的回答。 lowercase_shingle search_analyzer 来自另一个问题,来自答案stackoverflow.com/questions/53412408/… 但是当我正确理解 match_phrase 时,查询的所有部分都必须存在。 “ordner”永远不会出现,这就是为什么,它不会提升。你确定这应该有效吗?我试了一下(boost 500),结果和以前一样。
  • 哎呀,我错过了:(这行不通你是对的
【解决方案2】:

我通过使用带有自定义脚本的函数得分查询轻松解决了 I。

这个脚本成为完整的搜索词并做两件事: 根据值的长度设置分数(所以这里“ohne griffloch”比“griffloch”大,所以更好)。

第二个(可选,但对我来说很好)是,它使用文本中值的位置。

我需要做的是,删除值数组并将索引中的每个值作为一个文档。

"functions": [
              {

                "script_score": {
                  "script": {
                    "source": "def v=doc['filterValue'].value; def score = 10000; score += v.length(); score -= \"ordner ohne griffloch\".indexOf(v)*50;",
                    "lang": "painless"
                  }
                }
              }
            ],
            "score_mode": "multiply",
            "boost_mode": "replace",
            "max_boost": 3.4028235e+38,
            "boost": 1
          }

  }

【讨论】:

  • 如果我正在对多个字段进行 multi_match 搜索怎么办??
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-13
  • 1970-01-01
  • 1970-01-01
  • 2016-10-10
  • 2020-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多