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

Posted PacosonSWJTU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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全文检索:查询前,会对查询条件的值进行分词,然后再进行查询;

以上是关于6.elasticsearch查询与过滤上下文(query context与filter contenxt)以及term术语查询的主要内容,如果未能解决你的问题,请参考以下文章

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

在跨度关系中使用 Q 过滤

SOLR 过滤器查询与主查询

elasticsearch 查询与过滤

Elasticsearch Query DSL概述与查询过滤上下文

Django添加Q过滤器以查询相关对象存在时,条件查询