【问题标题】:Elasticsearch multi-match fields doesn't include query stringElasticsearch 多匹配字段不包括查询字符串
【发布时间】:2020-08-21 04:58:55
【问题描述】:

我正在使用以下查询对象进行多重匹配搜索:

{
    _source: [
        'baseline',
        'cdrp',
        'date',
        'description',
        'dev_status',
        'element',
        'event',
        'id'
    ],
    track_total_hits: true,
    query: {
        bool: {
            filter: [{name: "baseline", values: ["1f.0.1.0", "1f.1.8.3"]}],
            should: [
                {
                    multi_match:{
                        query: "national",
                        fields: ["cdrp","description","narrative.*","title","cop"]
                    }
                }
            ]
        } 
    },
    highlight: { fields: { '*': {} } },
    sort: [],
    from: 0,
    size: 50
}

我希望在描述或叙述中找到“国家”一词。* 字段,但返回的 2 条记录中只有一条符合我的预期。我正在尝试了解原因。

elasticsearch.config.ts

"settings": {
    "analysis": {
        "analyzer": {
            "search_synonyms": {
                "tokenizer": "whitespace",
                "filter": [
                    "graph_synonyms",
                    "lowercase",
                    "asciifolding"
                ],
            }
        }
    }
},

"mappings": {
    "properties": {
        "description": {
            "type": "text",
            "analyzer": "search_synonyms"
        },
        "narrative": {
            "type":"object",
            "properties":{
                "_all":{
                    "type": "text",
                    "analyzer": "search_synonyms"
                }
            }
        },
    }
}

【问题讨论】:

  • 也分享示例文档。
  • @shAkur multi_match 查询是 should 子句的一部分,因此只会影响评分。所有文件将被退回。具有“国家”的文件将获得更高的分数。如果你打算过滤 "national" ,你应该把它移到 filter 子句下
  • 我希望过滤器与描述和叙述。* 字段进行“与”运算,因此“国家”一词应位于其中一个文本字段中。在过滤器中移动 multi_match 对象可以解决问题,还是使用 must 会更好?

标签: elasticsearch indexing filter analyzer


【解决方案1】:

Should 子句的工作方式类似于 OR,它不会过滤掉影响评分的文档。匹配 should 子句的文档得分较高。

如果你想过滤多重匹配,你可以将它移到过滤子句中

filter: [
           {
              name: "baseline", values: ["1f.0.1.0", "1f.1.8.3"]
           },
           {
               multi_match:
               {
                     query: "national",
                     fields: ["cdrp","description","narrative.*","title","cop"]
               }
           }
        ]

Filter vs Must:- 两者都返回指定的匹配子句的文档。过滤器不对文档进行评分。因此,如果您对文档分数不感兴趣或不关心返回文档的顺序,则可以使用过滤器。所以两者都是一样的,只是得分不同。

匹配越多的文档得分越高

Multi_match 默认使用best_fields

查找与任何字段匹配的文档,但使用来自 最好的领域。

它使用为具有最大匹配数的字段返回的分数来计算每个文档的分数。

例子

文档 1 在两个字段中匹配,字段 1(得分 2),字段 2(得分 1)

文档 2 在一个字段中匹配,字段 2(得分 3)

即使有 1 个字段匹配,Documnet 2 的排名也会更高。

你可以把它改成 most_fields

查找与任何字段匹配的文档并结合来自的 _score 每个字段。

{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "test",
            "fields": [],
            "type": "most_fields"
          }
        }
      ]
    }
  }
}

由于多个词条导致的字段得分高,匹配字段数较少的文档仍然可以排名较高。

如果您想为单个字段赋予相同的分数,而不管匹配的标记数量。你需要使用constant_score查询

{
  "query": {
    "bool": {
      "should": [
        {
          "constant_score": {
            "filter": {
              "term": {
                "field1": "test"
              }
            }
          }
        },
        {
          "constant_score": {
            "filter": {
              "term": {
                "field2": "test"
              }
            }
          }
        }
      ]
  }
},
  "highlight": {
    "fields": {
      "field1": {},
      "field2": {}
    }
  }
}

结果:

"hits" : [
      {
        "_index" : "index18",
        "_type" : "_doc",
        "_id" : "iSCe6nEB8J88APx3YBGn",
        "_score" : 2.0, --> one score per field matched
        "_source" : {
          "field1" : "test",
          "field2" : "test"
        },
        "highlight" : {
          "field1" : [
            "<em>test</em>"
          ],
          "field2" : [
            "<em>test</em>"
          ]
        }
      },
      {
        "_index" : "index18",
        "_type" : "_doc",
        "_id" : "iiCe6nEB8J88APx3ghF-",
        "_score" : 1.0,
        "_source" : {
          "field1" : "test",
          "field2" : "abc"
        },
        "highlight" : {
          "field1" : [
            "<em>test</em>"
          ]
        }
      },
      {
        "_index" : "index18",
        "_type" : "_doc",
        "_id" : "iyCf6nEB8J88APx3UhF8",
        "_score" : 1.0,
        "_source" : {
          "field1" : "test do",
          "field2" : "abc"
        },
        "highlight" : {
          "field1" : [
            "<em>test</em> do"
          ]
        }
      }
    ]
  }

【讨论】:

  • 感谢您的回答。文档评分很重要,但是我必须更改它并使用每个文档的高亮数来构建分数。你知道我该怎么做吗?
  • @shAkur 默认匹配数越多得分越高
  • 不幸的是,我的结果似乎并非如此。对于搜索,我得到 3 个结果:第一个有 3 个亮点,第二个有一个亮点,第三个有 2 个亮点。我需要根据找到的亮点数量来订购它们
  • @shAkur 你能添加你正在执行的查询吗
  • 它与我在上面第一个代码 sn-p 中输入的查询相同,但 query.bool.filter 为空,并且“这是一个非常长的文本字段”为 multi_match query。我认为默认的排序算法是基于相关性而不是亮点的数量。我错了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 2018-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多