ES实战Term查询未命中问题

Posted 顧棟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES实战Term查询未命中问题相关的知识,希望对你有一定的参考价值。

文章目录


Term查询未命中问题

问题

Search使用term查询未命中数据

采用索引自动创建模式-写入数据

POST gudong20230111/_doc
"fundCode":"SSS000"

term查询

GET  /gudong20230111/_doc/_search

    "query": 
        "bool": 
            "must": [
                 "term":  "fundCode":"SSS000" 
            ]
        
    

结果未命中


    "took": 2,
    "timed_out": false,
    "_shards": 
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    ,
    "hits": 
        "total": 0,
        "max_score": null,
        "hits": []
    

检查索引配置

GET  /gudong20230111/_mappings

    "gudong20230111": 
        "mappings": 
            "_doc": 
                "properties": 
                    "fundCode": 
                        "type": "text",
                        "fields": 
                            "keyword": 
                                "type": "keyword",
                                "ignore_above": 256
                            
                        
                    
                
            
        
    

发现fundCode字段类型是text,未指明分词器,会采用默认的标准分词器进行文本分析。

检查文本分析效果

通过_analyze api得到文本分词效果

POST _analyze

  "analyzer": "standard",
  "text":     "SSS000"


    "tokens": [
        
            "token": "sss000",
            "start_offset": 0,
            "end_offset": 6,
            "type": "<ALPHANUM>",
            "position": 0
        
    ]

发现分析出的词汇是小写的,所以在使用大写的数据进行查询的时候,会查询不到,


总结

term查询

term级别查询是对存储在倒置索引中的单词或词汇进行操作,并且在执行前仅对具有normalizer属性的keyword类型的字段进行规范化处理。term级别查询通常用于数字、日期和枚举等结构化数据,而不是全文字段。

term查询的前提

字段的文本需要经过文本分析,形成词汇。需要字段类型为text,采用默认标准分词器或者自定义分词器。

默认分词器-标准分词器

standard 分析器是默认的分词器,如果没有指定则使用。 它提供基于语法的标记化(基于 Unicode 标准附件 #29 中指定的 Unicode 文本分段算法),并且适用于大多数语言。

内置的标准分析器包含以下部分:

  • 分词器:英文分词可以根据空格将单词分开,中文分词比较复杂,可以采用机器学习算法来分词。

  • Token过滤器:对切分的单词进行加工。

指定分词器

  • 通过mapping指定

    PUT my_index
    
      "mappings": 
        "_doc": 
          "properties": 
            "code": 
              "type": "keyword"
            ,
            "name": 
              "type": "text",
              "analyzer": "english",
              "search_analyzer": "standard"
            
          
        
      
    
    
  • URL Search上使用analyer参数

  • Request Body Search 中DSL语法

    GET gudong20230111/_doc/_search
    
        "query": 
            "match": 
                "fundCode": 
                    "query": "SSS000",
                    "analyzer": "standard"
                
            
        
    
    

测试分词效果

analyze API

POST _analyze

  "analyzer": "whitespace",
  "text":     "The quick brown fox."


POST _analyze

  "tokenizer": "standard",
  "filter":  [ "lowercase", "asciifolding" ],
  "text":      "Is this déja vu?"

不进行分词

将字段变为keyword,不会进行分词操作,keyword主要用于聚合和排序

text主要用于全文检索。

字段即分词又不分词

为不同的目的以不同的方式对同一字段进行索引往往是有用的。这就是多字段的目的。例如,一个字符串字段可以被映射为text字段用于全文搜索,也可以被映射为keyword字段用于排序或聚合。

PUT my_index

  "mappings": 
    "_doc": 
      "properties": 
        "city": 
          "type": "text",
          "fields": 
            "raw":  
              "type":  "keyword"
            
          
        
      
    
  


PUT my_index/_doc/1

  "city": "New York"


PUT my_index/_doc/2

  "city": "York"


GET my_index/_search

  "query": 
    "match": 
      "city": "york" 
    
  ,
  "sort": 
    "city.raw": "asc" 
  ,
  "aggs": 
    "Cities": 
      "terms": 
        "field": "city.raw" 
      
    
  

  • city.raw字段是city字段的一个keyword类型版本。
  • city 字段可用于全文搜索
  • city.raw字段可用于排序和聚合

多字段的另一个用例是以不同的方式分析同一字段,以提高相关性。例如,我们可以用标准分析器对一个字段进行索引,该分析器将文本分解成单词,并再次用英语分析器将单词分成词根形式。

PUT my_index

  "mappings": 
    "_doc": 
      "properties": 
        "text":  
          "type": "text",
          "fields": 
            "english":  
              "type":     "text",
              "analyzer": "english"
            
          
        
      
    
  


PUT my_index/_doc/1
 "text": "quick brown fox"  

PUT my_index/_doc/2
 "text": "quick brown foxes"  

GET my_index/_search

  "query": 
    "multi_match": 
      "query": "quick brown foxes",
      "fields": [ 
        "text",
        "text.english"
      ],
      "type": "most_fields" 
    
  

  • text字段使用standard分析器。
  • text.english字段使用english分析器。
  • 写入两个文档,一个是fox,另一个是foxes
  • 查询texttext.english字段,并结合得分。

文本字段在第一个文件中包含术语fox,在第二个文件中包含foxes。text.english字段在两个文档中都包含fox,因为foxes被单词汇化为fox。

查询字符串也由标准分析器对文本字段进行分析,并由英语分析器对text.english字段进行分析。干系字段允许对狐狸的查询也匹配只包含fox的文档。这使我们能够匹配尽可能多的文件。通过同样查询未单词化的“文本”字段,我们提高了与“fox”完全匹配的文档的相关性得分。

以上是关于ES实战Term查询未命中问题的主要内容,如果未能解决你的问题,请参考以下文章

ElasticSearch:给定一个文档和一个查询,相关性得分是多少?

【ES从入门到实战】十七、全文检索-ElasticSearch-进阶-aggregations聚合分析

es 基础概念总结 —— Request Body Search

elasticsearch检索,聚合,建模,优化--《elasticsearch核心技术与实战》笔记

ES查询-term VS match (转)

es中的term和match的区别