6.elasticsearch查询与过滤上下文(query context与filter contenxt)以及term术语查询

【README】

1.本文总结自:

Query and filter context | Elasticsearch Guide [7.2] | Elastichttps://www.elastic.co/guide/en/elasticsearch/reference/7.2/query-filter-context.html2.文档相关性分数是否被计算,取决于查询子句是在查询上下文,还是在 过滤器上下文;

  • 过滤器上下文(filter context)不计算分数 ;

【1】相关性分数

默认情况下,elasticsearch根据相关性分数对匹配结果排序,该分数衡量了一个文档对查询条件的匹配程度;

  • 即使每一种查询根据不同方式计算出相关性分数,但计算分数与否取决于 查询子句是在 查询(query)还是在 过滤器(filter)的上下文中运行
    • 查询上下文要计算分数;
    • 过滤器上下文不计算分数;

【1.1】查询上下文(query context)

在查询上下文中,查询子句回答了这个问题,即这个文档与查询子句的匹配程度如何?;

  • 除了决定文档是否匹配外,查询子句还计算了 _score元字段的相关性分数
  • 只要把查询子句传递给查询参数(如搜索api中的查询参数),查询上下文就会生效;

【1.2】过滤器上下文(filter context)

1)在过滤器上下文中, 查询子句回答了这个问题,即这个文档是否匹配查询子句? 回答是简单的yes 或者 no;不会计算分数

2)过滤器上下文总是用于过滤结构化数据,如:

  • 是否这个时间戳在 2015和2016之间?
  • 是否 status字段设置为 published?

3)频繁使用的过滤器会被自动化缓存,以加速查询性能;

4)只要把查询子句传递给 filter 的参数,过滤器就会生效

  • 如 bool查询中的 filter 或 must_not 参数;
  • constant_score 查询中的 filter参数或filter聚合;

【2】查询与过滤器上下文例子

下面的例子是 查询api中 查询和过滤器上下文使用了查询子句。

这个查询会匹配哪些满足以下条件的文档:

  • address 包含单词 Holmes;
  • employer 字段包含单词  Pyrami;
  • gender 字段包含 精确单词 M(精确的意思是 等于);
  • age 字段包含大于28的文档;
post localhost:9200/bank/_search 

{
    "query":{
        "bool":{
            "must":[
                {"match":{"address":"Holmes"}}
                ,{"match":{"employer":"Pyrami"}}
            ]
           , "filter":[
                 {
                     "range":{"age":{"gte":28}}
                 }
                 , {
                     "term":{"gender.keyword":"M"}
                 }
            ]
        }
    }
}

// 查询结果 
{
    "took": 8,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 13.007463,
        "hits": [
            {
                "_index": "bank",
                "_type": "account",
                "_id": "1",
                "_score": 13.007463,
                "_source": {
                    "account_number": 1,
                    "balance": 39225,
                    "firstname": "Amber",
                    "lastname": "Duke",
                    "age": 32,
                    "gender": "M",
                    "address": "880 Holmes Lane",
                    "employer": "Pyrami",
                    "email": "amberduke@pyrami.com",
                    "city": "Brogan",
                    "state": "IL"
                }
            }
        ]
    }
} 

【查询dsl解说】

  • query参数:表示查询上下文;
  • bool 和 两个match子句用于查询上下文,这意味着它们对每个文档的匹配程度进行评分;
  • filter参数:表示过滤上下文;
  • term和 range子句用于过滤上下文。它们过滤掉不匹配的文档,但不影响匹配文档的分数;

【3】term术语查询

1)参考文档:  Term query | Elasticsearch Guide [7.2] | Elastic

2)上述例子中,term术语查询子句如下:

"term":{"gender.keyword":"M"}

term查询中为什么要查询gender.keyword 等于M的文档,而不是查询 gender 等于M的文档呢?

原因如下:因为 gender是 text类型字段,elasticsearch在保存文档时,会分析及分词,这样就会修改字段的原生值。如,标准分词器会把 text类型字段的值 做如下修改:

  • step1)移除大部分标点符号;
  • step2)把原生内容切分为单个单词,称为token(标记);
  • step3)把token标记转为小写;

所以经过上述转换后, id等于1的文档的gender原生值是M,文档在保存时,elasticsearch会将其修改为m

又 term精确匹配 M ,所以 1号文档显然不满足 term精确匹配的条件;

3)那如何使得 term精确匹配起作用呢(在不使用keyword的情况下)

显然 term精确匹配这样写即可。gender匹配m,而不是M

"term":{"gender":"m"}

【小结】term术语查询

  • 对于 text类型的字段,不建议使用 term做精确匹配查询,而建议使用 match 全文检索
  • 对于 keyword 类型的字段,建议使用 term做精确匹配查询;

【区别】term精确匹配与match全文检索的区别         

  • term精确匹配:查询前,不会对查询条件的值进行分词,直接进行查询;而text类型字段的值在文档被存储时就已经分词了,text字段的原生值被切分为多个独立的单词;
  • match全文检索:查询前,会对查询条件的值进行分词,然后再进行查询;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值