Py学习  »  Elasticsearch

Elasticsearch-如果匹配的单词越多,文档得分越高

Marcel Balzer • 6 年前 • 1144 次点击  

我有个问题,希望有人能帮助我。

我有一个搜索匹配查询的简单示例

"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”作为第一个(更好的分数),因为它匹配更多的单词。但我发现第一个有更好的分数,我认为,因为它包含更多的“格里夫洛赫”。

我不能使用术语查询,因为当查询包含其他单词(这里是“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"
        }
      }
    }
  }
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/50633
文章 [ 2 ]  |  最新文章 6 年前
Marcel Balzer
Reply   •   1 楼
Marcel Balzer    7 年前

我用一个带有自定义脚本的函数score查询解决了这个问题。

此脚本将成为完整的搜索项,并执行两项操作: 根据值的长度设置分数(因此这里的“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
          }

  }
Pierre Mallet
Reply   •   2 楼
Pierre Mallet    7 年前

您应该在查询中添加短语匹配的增强。因此,在多个filterValues中找到所有查询项的文档自然会得到增强。

但你得小心这个怪癖( see here, official doc )

我不知道是怎么回事(也许你身上有原力),但你的地图已经对了 position_increment_gap 但是你应该删除设置

search_analyzer:“小写_shingle”

因为在你的背景下似乎有点奇怪。

然后我们在匹配短语上加上boost

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

                    }
                }
            ]
        }
    }
}

希望能成功!

评论后编辑:

如果更改映射,以便在索引时使用shingle_分析器添加子字段

"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子字段上添加一个boost

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

在你的例子中,第二个博士而不是第一个博士