在Elasticsearch中正确排序以进行完全匹配和“开头为”(前缀)

我需要使用Elasticsearch改进搜索结果列表。

假设我们有3个文档,其中包含单个字段和内容,如下所示:

  • “苹果”
  • “青苹果”
  • “苹果树”

如果我搜索“苹果”,可能会发生这样的情况:我得到的排序结果如下:

  • “青苹果”
  • “苹果树”
  • “苹果”

但是我想要的是具有最高分数的精确匹配项,这里是带有“ apple”的文档。

下一个最高分应该是搜索词开头的条目,这里是“ apple tree”,其余按默认方式排序。

所以我想要这个:

  • “苹果”
  • “苹果树”
  • “青苹果”

我试图通过使用rescore实现它:

curl -X GET "http://localhost:9200/my_index_name/_search?size=10&pretty" -H 'Content-Type: application/json' -d'

{

"query": {

"query_string": {

"query": "apple"

}

},

"rescore": {

"window_size": 500,

"query": {

"score_mode": "multiply",

"rescore_query": {

"bool": {

"should": [

{

"match": {

"my_field1": {

"query": "apple",

"boost": 4

}

}

},

{

"match": {

"my_field1": {

"query": "apple*",

"boost": 2

}

}

}

]

}

},

"query_weight": 0.7,

"rescore_query_weight": 1.2

}

}

}'

但这并不是真的有效,因为Elasticsearch似乎用空格将所有单词分隔开。例如,搜索“ apple *”也将提供“ green

apple”。这似乎是recore无法为我工作的原因。

可能还有其他字符,例如点“。”,“-”,“;” 等等,Elasticsearch用来拆分和弄乱我的排序。

我还在“ rescore_query”中使用了“ match_phrase”,而不是“ bool”,但是没有成功。

我也尝试过只有一场比赛:

curl -X GET "http://localhost:9200/my_index_name/_search?size=10&pretty" -H 'Content-Type: application/json' -d'

{

"query": {

"query_string": {

"query": "apple"

}

},

"rescore": {

"window_size": 500,

"query": {

"score_mode": "multiply",

"rescore_query": {

"bool": {

"should": [

{

"match": {

"my_field1": {

"query": "apple*",

"boost": 2

}

}

}

]

}

},

"query_weight": 0.7,

"rescore_query_weight": 1.2

}

}

}'

它似乎可行,但我仍然不确定。这是正确的方法吗?

EDIT1:对于其他查询,一个匹配重新评分无法正常工作。

回答:

您唯一需要在分数上进行操作的地方是完全匹配,否则按词条位置的顺序将为您提供正确的顺序。让我们通过以下内容了解这一点:

首先创建一个映射,如下所示:

PUT test

{

"mappings": {

"_doc": {

"properties": {

"my_field1": {

"type": "text",

"analyzer": "whitespace",

"fields": {

"keyword": {

"type": "keyword"

}

}

}

}

}

}

}

我已经创建了my_field1带有whitespace分析器的字段,以确保通过仅将空格用作定界符来创建令牌。其次,我创建了一个名为keywordtype

的子字段keywordkeyword将保存输入字符串的非分析值,我们将使用它进行精确匹配。

让我们向索引添加一些文档:

PUT test/_doc/1

{

"my_field1": "apple"

}

PUT test/_doc/2

{

"my_field1": "apple tree"

}

PUT test/_doc/3

{

"my_field1": "green apple"

}

如果使用以下查询搜索术语apple,则文档的顺序将为2、1、3。

POST test/_doc/_search

{

"explain": true,

"query": {

"query_string": {

"query": "apple",

"fields": [

"my_field1"

]

}

}

}

"explain": true在上面的查询中,在输出中给出分数计算步骤。阅读本文将使您了解文档的评分方式。

我们需要做的就是提高得分以实现完全匹配。我们将对场进行精确匹配my_field1.keyword。您可能有一个问题,为什么不这样呢my_field1。这样做的原因是因为my_field1经过分析,当为3个文档的输入字符串生成令牌时,都会针对此字段存储一个令牌(术语)apple(以及其他术语(例如,tree对于doc

2和greendoc 3,如果存在其他术语))

。当我们在此字段上对术语进行完全匹配时,apple所有文档都会匹配,并且对每个文档的得分都会产生相似的影响,因此得分没有变化。由于只有一个文档具有applemy_field1.keyword该文档(文档1)相对的确切值,因此可以匹配精确查询,因此我们将对其进行增强。因此查询将是:

{

"query": {

"bool": {

"should": [

{

"query_string": {

"query": "apple",

"fields": [

"my_field1"

]

}

},

{

"query_string": {

"query": "\"apple\"",

"fields": [

"my_field1.keyword^2"

]

}

}

]

}

}

}

{

"took": 9,

"timed_out": false,

"_shards": {

"total": 5,

"successful": 5,

"skipped": 0,

"failed": 0

},

"hits": {

"total": 3,

"max_score": 1.7260925,

"hits": [

{

"_index": "test3",

"_type": "_doc",

"_id": "1",

"_score": 1.7260925,

"_source": {

"my_field1": "apple"

}

},

{

"_index": "test3",

"_type": "_doc",

"_id": "2",

"_score": 0.6931472,

"_source": {

"my_field1": "apple tree"

}

},

{

"_index": "test3",

"_type": "_doc",

"_id": "3",

"_score": 0.2876821,

"_source": {

"my_field1": "green apple"

}

}

]

}

}

以上是 在Elasticsearch中正确排序以进行完全匹配和“开头为”(前缀) 的全部内容, 来源链接: utcz.com/qa/435247.html

回到顶部