ES之单字符串多字段查询:multi_match

在es的查询中,有两个指标非常重要:

一是准确率,查询到的结果集中包含的正确结果数占比;

二是召回率,就是查到的结果集中正确结果在所有正确结果(包含查询到的和未查询到的)中的占比。

在单字符串多字段查询过程中,考虑到正确率,就是要把匹配度最高的放在最前面;考虑到召回率就是就可能多的把相关文档都查出来。

在es中,multi_match就是针对单字符串多字段查询的解决方案,包括三种查询:best_fields,most_fields,cross_fields。

一,best_fields

多字段查询中,单字段匹配度最高的那个文档的算分最高。

插入测试数据:
PUT multi_query_index/_bulk
{"index":{"_id":1}}
{"title":"my bark dogs","body":"cats and dogs"}
{"index":{"_id":2}}
{"title":"my cat mimi","body":"of barking dogs"}
先用bool查询来一波

按照常规理解,第二个文档的body属性中有barking dogs,应该匹配度最高。但结果却是文档1算分最高,排在最前面。

但是考虑到以下几个原因:

一是分词会将barking和dogs还原为bark和dog,这样算起这两个词在文档1一共出现了三次,在文档2中出现了两次,文档1的匹配度最高。

二是,在文本搜索中barking dogs并非整体作为一个关键字去搜索,而是被分词后进行搜索。

三是,bool查询会对每一个match query进行加权平均算分。

GET multi_query_index/_search
{
  "query": {
     "bool": {
       "should": [
         {
           "match": {
             "title":  "barking dogs"
           }
         },
         {
           "match": {
             "body":  "barking dogs"
           }
         }
       ]
     }
  }
}
使用multi_query的best_fields来一波

multi_query默认是best_fields模式,即找出匹配度最高的字段的算分作为整个查询的最高算分。这样的话,第二个文档算分就最高了。

GET multi_query_index/_search
{
  "explain": true, 
  "query": {
    "multi_match": {
      "type": "best_fields", 
      "query": "barking dogs",
      "fields": ["title","body"]
    }
  }
}

当然,在这个查询中,我们可以指定字段权重,突出某个字段的评分

GET multi_query_index/_search
{
  "explain": true, 
  "query": {
    "multi_match": {
      "type": "best_fields", 
      "query": "barking dogs",
      "fields": ["title^10","body"]
    }
  }
}

本质上,multi_match/best_field查询被转换为一个disjunction query。

二,most_fields

most fields字段主要是利用multifields特性,在索引的mapping中对字段设置多个字段,该字段的分词器采用标准分词器,这样的话,分词只会根据空格拆分,而不会对单词进行主干提取。

PUT /multi_query_most_fields
{
    "settings": { "number_of_shards": 1 }, 
    "mappings": {
        "my_type": {
            "properties": {
                "title": { 
                    "type":     "string",
                    "analyzer": "english",
                    "fields": {
                        "std":   { 
                            "type":     "string",
                            "analyzer": "standard"
                        }
                    }
                }
            }
        }
    }
}
插入2条数据
PUT /multi_query_most_fields/_doc/1
{ "title": "My rabbit jumps" }

PUT /multi_query_most_fields/_doc/2
{ "title": "Jumping jack rabbits" }
针对title单字段来一波multi query查询

这波查询,两个文档的算分一样,但显然第二个文档的算分应该高一些,这就是因为title使用的english分词器会将jumping还原为jump,rabbits还原为rabbit。

GET multi_query_most_fields/_search
{
  "query": {
    "multi_match": {
      "query": "jumping rabbits",
      "fields": ["title"],
      "type": "most_fields"
    }
  }
}
针对title及其multifields来一波multi query查询

这波查询,多了对title.std的查询,结果就是第二个文档的算分高,排在最前面,这是因为title.std使用了standard分词器。

GET multi_query_most_fields/_search
{
  "query": {
    "multi_match": {
      "query": "jumping rabbits",
      "fields": ["title","title.std"],
      "type": "most_fields"
    }
  }
}
这里,再尝试一次bool查询。

结果发现,bool查询的结果和multi_query/most_fields查询一致。

其实,multi_query/most_fields原理上就是被封装为一个bool查询的。

GET multi_query_most_fields/_search
{
  "query": {
    "dis_max": {
      "boost": 1.2,
      "queries": [
        {
          "match": {
            "title": "jumping rabbits"
          }
        },
        {
         "match": {
            "title.std": "jumping rabbits"
          }
        }
      ]
    }
  }
}

参考文献

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值