elasticsearch查询bool和多字段查询

本文详细介绍了Elasticsearch中的bool查询,包括Query Context和Filter Context的区别,以及bool复合查询如何针对多个字段设置多个条件。同时,文章探讨了单字符串多字段查询,如dis max query和multi match查询的不同应用场景和策略,如何根据需求选择最佳匹配的字段评分。通过对bool查询的深入理解和多字段查询的实践,能够更好地优化Elasticsearch的搜索性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

bool查询和多字段查询

bool

Query Context 和 Filter Context

es中有 query 和 filter 两种不同的 Context

  • query context : 相关性算分
  • filter context : 不需要算分 ( yes or no ),可以缓存cache,性能更高

bool 复合查询 针对多个字段包含多个条件

一个 bool 查询,支持一个或多个查询子句的组合

  • 子查询可以任意顺序,可以嵌套多个查询
  • 若bool查询中没有must条件,should中必须至少满足一条查询,若有must,则should可不满足条件返回
  • 总共包括四种子句,两种影响算分,两种不影响算分,都支持数组
must必须匹配 支持数组,算分
should选择性匹配 支持数组 ,算分
must_notfilter context 查询子句,必须不能匹配 支持数组,不算分
filterfilter context 必须匹配 支持数组,不算分
  • 相关性算分除了全文本检索也适用于yes or no 的子句,匹配的子句越多,相关性算分越高。若多条查询子句被合并为一条复合查询语句如bool,则每个查询子句的评分会被合并到总的相关性评分中
  • bool 下should算分过程:
    • 查询should语句中的多个查询
    • 加和多个查询的评分
    • 乘以匹配语句的总数
    • 除以所有语句的总数

bool 示例

select * from products where price = 30 and avaliable = "true" and price > 10 and (productID.keyword = "JODL-X-1937-#pV7" or productID.keyword = "XHDK-A-1293-#fJ3")
POST /products/_search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "price" : "30" }
      },
      "filter": {
        "term" : { "avaliable" : "true" }
      },
      "must_not" : {
        "range" : {
          "price" : { "lte" : 10 }
        }
      },
      "should" : [  
        { "term" : { "productID.keyword" : "JODL-X-1937-#pV7" } },
        { "term" : { "productID.keyword" : "XHDK-A-1293-#fJ3" } }
      ],
      "minimum_should_match" :1
    }
  }
}

示例2:

select id from table where user = "kimchy" and tag = "tech" and age not between 10 and 20 and (tag = "wow" or tag = "elasticsearch") order by create_time desc limit 10, 20
POST /table/_search
{
  "_source": ["id"],
  "from":10,
  "size":20,
  "sort":[{"create_time":"desc"}], 
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

bool 嵌套示例 should 可以继续嵌套 bool

#嵌套,实现了 should not 逻辑
POST /products/_search
{
  "query": {
    "bool": {
      "must": {
        "term": {
          "price": "30"
        }
      },
      "should": [
        {
          "bool": {
            "must_not": {
              "term": {
                "avaliable": "false"
              }
            }
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

bool 嵌套查询层级也会影响算法 也可用boost控制字段权重

  • 同一层级下的竞争字段具有相同的权重
POST /animals/_search
{
  "query": {
    "bool": {
      "should": [
        { "term": { "text": "quick" }},
        { "term": { "text": "dog"   }},
        {
          "bool":{
            "should":[
               { "term": { "text": "brown" }},
                 { "term": { "text": "red" }},
            ]
          }
        }
      ]
    }
  }
}

brown和red加起来才有quick或dog相同的权重

单字符串多字段查询

dis max query

在bool查询下的should,其查询子句不同字段算分相互竞争(即所有查询子句一起贡献评分),若不想将分数简单叠加而是找出单个查询最佳匹配的字段的评分则使用 dis_max

disjunction max query : 将任何与任一查询匹配的文档作为结果返回,采用字段上最匹配的评分最终评分返回(即取所有查询子句的最高评分返回)

dis_max:

  • 参数 queries 格式数组
  • tie_breaker: 一个0-1的浮点数,0代表最佳匹配,1代表所有语句(查询子句)同等重要
tie_breaker 在评分流程中作用
  获取最佳匹配语句的评分 _score
  对其他匹配语句的评分与 tie_breaker 相乘(所以tie_breaker默认值0)
  对以上评分求和并规范化

dis_max示例

# title 和 body 共享评分
POST /blogs/_search
{
    "query": {
        "bool": {
            "should": [
                { "match": { "title": "Brown fox" }},
                { "match": { "body":  "Brown fox" }}
            ]
        }
    }
}
# title 和 body 其中一个字段独享评分
POST blogs/_search
{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "Quick pets" }},
                { "match": { "body":  "Quick pets" }}
            ]
        }
    }
}
# tie_breaker
POST blogs/_search
{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "Quick pets" }},
                { "match": { "body":  "Quick pets" }}
            ],
            "tie_breaker": 0.2
        }
    }
}

multi match

单字符串多字段存在三种场景:

  • 最佳字段 best_fields(默认default):当字段之间相互竞争又相互关联,评分来自最匹配字段
  • 多数字段 most_fields:处理英文内容时,一般在主字段(分词器)提取词干,加入同义词,以匹配更多的文档。相同的文档加入子字段(分词器),以提供更精确的匹配。其他字段作为匹配文档提高相关度的信号。匹配字段越多则越好,希望在找到尽可能多的字段
  • 混合字段 cross_fields:对于 某些实体,如姓,名,省,市等,需要在多个字段中确定信息,单个字段只作为整体的一部分。希望在任何这些列出的字段中找到尽可能多的词

注意:multi match query的best field和dis_max query效果一致

{
  "dis_max": {
    "queries":  [
      {
        "match": {
          "title": {
            "query": "Quick brown fox",
            "minimum_should_match": "30%"
          }
        }
      },
      {
        "match": {
          "body": {
            "query": "Quick brown fox",
            "minimum_should_match": "30%"
          }
        }
      },
    ],
    "tie_breaker": 0.3
  }
}
等同
{
    "multi_match": {
        "query":                "Quick brown fox",
        "type":                 "best_fields",       #1
        "fields":               [ "title", "body" ],
        "tie_breaker":          0.3,
        "minimum_should_match": "30%"                #2 minimum_should_match 或 operator 这样的参数会被传递到生成的 match 查询中。
    }
}

multi_match格式:参数支持 type query fields tie_breaker minimum_should_match

# minimum_should_match 等参数可以传递到生成的query中
POST blogs/_search
{
  "query": {
    "multi_match": {
      "type": "best_fields", # best_fields是默认类型 可以不指定
      "query": "Quick pets",
      "fields": ["title^2","body"], # fields 支持权重操作 ^提权值
      "tie_breaker": 0.2,  # 评分机制
      "minimum_should_match": "20%"   # 向下取整
    }
  }
}

分词匹配示例

PUT /titles
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "english", # 分词更匹配 提取词干
        "fields": {"std": {"type": "text","analyzer": "standard"}} # 分词更精确 保留原始单词
      }
    }
  }
}

POST titles/_bulk
{ "index": { "_id": 1 }}
{ "title": "My dog barks" }
{ "index": { "_id": 2 }}
{ "title": "I see a lot of barking dogs on the road " }

GET /titles/_search
{
   "query": {
        "multi_match": {
            "query":  "barking dogs",
            "type":   "most_fields",
            "fields": [ "title^10", "title.std" ]
        }
    }
}

multi_match跨字段搜索示例:

可以copy_to 解决跨字段 但要额外存储空间
multi_match 跨字段搜索支持使用operator

GET address/_search
{
  "query": {
    "multi_match": {
      "query": "省 市 街道",
      "type": "cross_fields", # 相当于把多个字段拼成一个字段匹配更多词项
      "fields": ["street", "city", "country"],  
      "operator": "and"  
    }
  }
}

注意

  • minimum_should_match 或 operator 这样的参数会被传递到生成的 match 查询query中
  • 查询字段名称的可模糊匹配 “fields”: “*_title”
  • 可提升单个字段的权重 “fields”: [ “*_title”, “title.std^2” ]
  • multi_match 的type 分三种策略best_fields、most_fields、cross_fields
  • multi_match 和 bool ,dis_max,query_string,match,boosting,term level 同层级
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值