ElasticSearch(ES) 搜索入门笔记

news/2024/7/7 5:53:41 标签: elasticsearch, 笔记, ES

文章目录

  • ElasticSearch(ES) 搜索入门笔记
    • 环境准备-本地安装ES和Kibana
    • mapping
      • 字段类型
      • mapping 参数
      • Analyzer
      • 自定义分析器
        • 分析器的测试
        • 中文分词 ik_max
        • Normalizer
      • 其他关于mapping的要点
    • ES 搜索
      • [match all 查询](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-all-query.html)
      • 精准搜索
      • 全文检索
      • 复合搜索
      • ES 搜索时的分数是如何计算的
        • 解释搜索结果
    • python ES 客户端
    • 参考资料

ES__1">ElasticSearch(ES) 搜索入门笔记

ElasticSearch简称ES,经过多年的发展,已是很流行的搜索工具了,无需多介绍,下面就粘一点官方介绍

You know, for search (and analysis)

Elasticsearch is the distributed search and analytics engine at the heart of the Elastic Stack. Logstash and Beats facilitate collecting, aggregating, and enriching your data and storing it in Elasticsearch. Kibana enables you to interactively explore, visualize, and share insights into your data and manage and monitor the stack. Elasticsearch is where the indexing, search, and analysis magic happens.

https://www.elastic.co/guide/en/elasticsearch/reference/current/elasticsearch-intro.html

ESKibana_11">环境准备-本地安装ES和Kibana

为了更好的学习和理解ES,可以在自己电脑上安装一个ES

  1. 在官方网站下载所需版本 https://www.elastic.co/cn/downloads/elasticsearch

  2. 将下载的文件解压到指定目录

    tar -xzf /Users/cc/Downloads/elasticsearch-8.11.3-darwin-aarch64.tar.gz -C /Applications
    
  3. 然后进入安装目录执行 ./bin/elasticsearch 以启动ES(注:较高的ES版本是以安全模式启动的; Windows上的启动命令为./bin/elasticsearch.bat

  4. 验证是否正常启动 curl -k -u elastic:password https://localhost:9200 (注:以前未以安全模式启动时不需要输入用户名和密码 curl 'http://localhost:9200/?pretty'

为了更方便学习和调试ES,可以使用Kibana提供的图形化开发工具,本地安装过程也很简单,如下所示:

  1. 在官方网站下载所需版本 https://www.elastic.co/downloads/kibana

  2. 将下载的文件解压到指定目录

    tar -xzf /Users/cc/Downloads/kibana-8.11.3-darwin-aarch64.tar.gz -C /Applications
    
  3. 然后进入安装目录执行 ./bin/kibana 以启动kinaba( Windows上的启动命令为./bin/kibana.bat

  4. kibana启动成功后需要去配置ES,可以在终端打印出的链接 http://localhost:5601/?code=971215 去配置,将ES启动时生成的enrollment token粘贴确认即可。(注:生成enrollment token的有效期是30分钟,过期后可以通过bin/elasticsearch-create-enrollment-token -s kibana --url https://localhost:9200 重新生成(命令里的–url必须指定,不然会报错ERROR: Failed to determine the health of the cluster. , with exit code 69) )

  5. 成功配置ES后,用ES的用户名密码登录后就可以正常使用kibina了,在kibana的首页左侧菜单栏-Management-Dev Tools 就可以看到图形化调试界面Console。(在ES的官方文档中的示例里的Console就是这个工具,使用它相比于使用curl来开发调试更方便)
    在这里插入图片描述

mapping

ES索引创建时定义的mapping相当于数据库中的表结构定义schema,它定义了索引中的字段名称和数据类型,以及字段倒排索引的相关配置如分词器、是否可索引等。

比如我们可以定义如下索引名为my-index-000001的索引,索引有三个字段age、email、name,对应的类型分别为integer、keyword、text。

 PUT /my-index-000001
{
  "mappings": {
    "properties": {
      "age":    { "type": "integer" }, 
      "email":  { "type": "keyword"  },
      "name":   { "type": "text"  }    
    }
  }
}

字段类型

这里记录下常见数据类型,更多ES定义类型参见ES官方文档定义的数据类型

  • text 是默认会被分词的字段类型,如果不指定分词器,ES会用标准分词器切分文本。

  • keyword 适用于保存不需要分词的原始文本,比如邮箱地址、id、标签、主机名等。

  • 数字类型有 long、integer、short、byte、double、float、half_float、scaled_float、unsigned_long。对整数类型(byte、short、integer、long)应选择满足业务场景范围的最小的整数类型。而对于浮点类型优先选择scaled_float会更高效,它有一个属性scaling_factor,用它转换后将数据存储为整型;当scaled_float无法满足要求时尽量选择满足业务场景的精度最小的类型。
    在这里插入图片描述

  • date 日期类型,格式可以是格式化的日期字符串如"2024-01-01" or "2024/01/01 12:10:30"、毫秒时间戳等。默认情况下,索引中的日期为UTC时间格式,其比北京时间晚8h,所以在使用date类型时务必注意时区。

  • boolean 布尔类型,存储true和false,也支持"false",“”(空字符,表示False) , "true"字符串。

  • binary, 可以存储如Base64编码字符,默认不被索引和搜索。

  • geo_point,可以存储经纬度相关信息,可以用来实现诸如查找在指定地理区域内相关的文档、根据距离来聚合文档、根据距离排序、根据地理位置修改评分规则等需求。

  • object 对象类型,字段本身也可以是一个object。

    假设定义如下索引

     PUT my-index-000001
    {
      "mappings": {
        "properties": {
          "region": {
            "type": "keyword"
          },
          "manager": {
            "properties": {
              "age":  { "type": "integer" },
              "name": {
                "properties": {
                  "first": { "type": "text" },
                  "last":  { "type": "text" }
                }
              }
            }
          }
        }
      }
    }
    

    并写入一条数据

     PUT my-index-000001/_doc/1
    { 
      "region": "US",
      "manager": { 
        "age":     30,
        "name": { 
          "first": "John",
          "last":  "Smith"
        }
      }
    }
    

    数据实际上被存储为

    {
      "region":             "US",
      "manager.age":        30,
      "manager.name.first": "John",
      "manager.name.last":  "Smith"
    }
    
  • nested 允许对每一项为object的列表索引后可以被独立查询。

    假设我们创建一个索引,其字段user类型是object,但是其实际数据是一个列表

     PUT my-index-000001
    {
      "mappings": {
        "properties": {
          "group": {
            "type": "keyword"
          },
          "user": {
            "properties": {
                  "first": { "type": "text" },
                  "last":  { "type": "text" }
              }
            }
        }
      }
    }
    

    写入一条数据

    PUT my-index-000001/_doc/1
    {
      "group" : "fans",
      "user" : [ 
        {
          "first" : "John",
          "last" :  "Smith"
        },
        {
          "first" : "Alice",
          "last" :  "White"
        }
      ]
    }
    

    因为object类型存储时会被ES 展平,所以数据存储的形式如下

    {
      "group" :        "fans",
      "user.first" : [ "alice", "john" ],
      "user.last" :  [ "smith", "white" ]
    }
    

    这时user.first和user.last的数据被存储成了一个列表,用户的first和last之间的关联被丢失了。如果我们有如下检索,ES仍可以返回答案:

    GET my-index-000001/_search
    {
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "Smith" }}
          ]
        }
      }
    }
    

    如果我们要去索引每一项为object的列表,并且希望维持列表中object的独立性,我们就需要使用nested类型了。

    如果我们将上面的例子的索引mapping的user定义为nested

     PUT my-index-000001
    {
      "mappings": {
        "properties": {
          "group": {
            "type": "keyword"
          },
          "user": {
            "type":"nested", 
            "properties": {
                  "first": { "type": "text" },
                  "last":  { "type": "text" }
              }
            }
        }
      }
    }
    

    再写入一条数据

    PUT my-index-000001/_doc/1
    {
      "group" : "fans",
      "user" : [
        {
          "first" : "John",
          "last" :  "Smith"
        },
        {
          "first" : "Alice",
          "last" :  "White"
        }
      ]
    }
    

    此时我们再运行下面查询语句,因为数据中不存在first为Alice,last为Smith的数据,检索结果为空

    GET my-index-000001/_search
    {
      "query": {
        "nested": {
          "path": "user",
          "query": {
            "bool": {
              "must": [
                { "match": { "user.first": "Alice" }},
                { "match": { "user.last":  "Smith" }} 
              ]
            }
          }
        }
      }
    }
    
  • 向量类型:dense_vector和sparse_vector 支持存储向量

mapping 参数

每个字段除了类型之外,还有其他属性可以定义,列举常用的属性:

  • dynamic: 控制一个字段是可以被动态地加入,比如说写入的数据里是否可以包含未定义的字段。其取值默认是true,也就是支持动态新增。我们可以定义整个索引的dynamic,字段是继承整个索引的dynamic,字段也可以再指定与索引不一样的取值。(通常企业里的ES会要求将dynamic设置为strict)
dynamic取值取值解释
trueNew fields are added to the mapping (default).
runtimeNew fields are added to the mapping as runtime fields. These fields are not indexed, and are loaded from _source at query time.
falseNew fields are ignored. These fields will not be indexed or searchable, but will still appear in the _source field of returned hits. These fields will not be added to the mapping, and new fields must be added explicitly.
strictIf new fields are detected, an exception is thrown and the document is rejected. New fields must be explicitly added to the mapping.
  • index:控制字段值是否会被索引,取值为true或false,默认是true。
  • store: ES默认不会存储字段的原始值,设置store为true可以存储原始值,并且在查询时,可以用stored_fields来获取字段的值。
  • enabled:设置为false时存储但是不会索引,默认为true。
  • copy_to: 允许将多个字段的值拷贝到一个组合字段中去,这个组合字段就能够像单个字段那样检索。

比如下面例子first_name 和last_name 可以被拷贝到full_name中用来查询

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "first_name": {
        "type": "text",
        "copy_to": "full_name" 
      },
      "last_name": {
        "type": "text",
        "copy_to": "full_name" 
      },
      "full_name": {
        "type": "text"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "first_name": "John",
  "last_name": "Smith"
}

GET my-index-000001/_search
{
  "query": {
    "match": {
      "full_name": { 
        "query": "John Smith",
        "operator": "and"
      }
    }
  }
}
  • fields 有时候我们想对一个字段用不同的方式来索引实现不同的目的,这就是multi-fields的目标。比如对于一个字符串字段我们可以定义为text类型实现全文检索,但是也想以keyword的形式来进行精确匹配或者聚合。我们甚至可以定义multi-field时都是text类型,但是使用不同的analyzer。

下面的例子,定义了类型为text的city字段,并定义了一个类型为keyword的city.raw字段

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "city": {
        "type": "text",
        "fields": {
          "raw": { 
            "type":  "keyword"
          }
        }
      }
    }
  }
}
  • ignore_above 超过ignore_above指定长度的字符串不会被索引或存储,一般是keyword类型字段会使用。

Analyzer

对于text字段,我们可以定义analyzer属性来指定如何对文本进行分析。

ES中定义了8种内置analyzer(分析器),如果不对text 字段指定分析器,默认使用的是standard Analyzer。


Standard Analyzer

The standard analyzer divides text into terms on word boundaries, as defined by the Unicode Text Segmentation algorithm. It removes most punctuation, lowercases terms, and supports removing stop words.

Simple Analyzer

The simple analyzer divides text into terms whenever it encounters a character which is not a letter. It lowercases all terms.

Whitespace Analyzer

The whitespace analyzer divides text into terms whenever it encounters any whitespace character. It does not lowercase terms.

Stop Analyzer

The stop analyzer is like the simple analyzer, but also supports removal of stop words.

Keyword Analyzer

The keyword analyzer is a “noop” analyzer that accepts whatever text it is given and outputs the exact same text as a single term.

Pattern Analyzer

The pattern analyzer uses a regular expression to split the text into terms. It supports lower-casing and stop words.

Language Analyzers

Elasticsearch provides many language-specific analyzers like english or french.

Fingerprint Analyzer

The fingerprint analyzer is a specialist analyzer which creates a fingerprint which can be used for duplicate detection.

内置analyzer可以无需配置就直接使用,一些analyzer也可以通过配置来改变其行为,比如standard analyzer 可以配置以支持停用词

## 定义一个mapping,其支持了停用词
PUT my-index-000001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "std_english": { 
          "type":      "standard",
          "stopwords": "_english_"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "type":     "text",
        "analyzer": "standard", 
        "fields": {
          "english": {
            "type":     "text",
            "analyzer": "std_english" 
          }
        }
      }
    }
  }
}

# 测试标准分析器的效果
POST my-index-000001/_analyze
{
  "field": "my_text", 
  "text": "The old brown cow"
}

# 测试使用配置停用词后的标准分析器的效果
POST my-index-000001/_analyze
{
  "field": "my_text.english", 
  "text": "The old brown cow"
}

ES中,触发文本分析的时机有两个:

  • 索引时:当索引映射中存在text字段时,默认会使用标准分析器进行文本分析,如果不喜欢默认的分析器,也可以在mapping中指定某个text类型字段使用其他分析器。
  • 全文检索时:对一个索引的text类型字段做全文检索时也会触发文本分析,这时文本分析的对象是搜索的内容。默认的分析器也是标准分析器,如果需要改变分析器,可以通过搜索参数analyzer进行设置。为了保持搜索效果的一致性,索引时的分析器和全文检索时的分析器一般会设置成相同的,但中文一般会在索引时设置更细的粒度的分词器,在搜索使用粒度更粗的分词器。

索引和检索时分析器设置举例:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "whitespace",
        "search_analyzer": "simple"
      }
    }
  }
}

自定义分析器

Elasticsearch规定,一个完整的文本分析过程需要经过大于等于零个character filters(字符过滤器)、一个tokenizers(分词器)、大于等于零个token filters(分词过滤器)的处理过程。文本分析的顺序是先进行字符过滤器的处理,然后是分词器的处理,最后是分词过滤器的处理。

  • character filters:用于对原始文本做简单的字符过滤和转换,例如ES内置的HTML strip字符过滤器可以用于方便地剔除文本中的HTML标签。ES 中定义了html_strip、mapping、pattern_replace三种内置character filters。
  • tokenizers:分词器的功能就是把原始的文本按照一定的规则切分成一个个单词,比如内置的 whitespace 分词器根据空格符来切分单词,会将 "Quick brown fox!" 变成 [Quick, brown, fox!]。分词器还会保留每个关键词在原始文本中出现的位置数据。Elasticsearch内置的分词器有几十种,通常针对不同语言的文本需要使用不同的分词器,当然也可以安装一些第三方的分词器来扩展分词的功能,比如中文分词常用ik分词器。
  • token filters:对用分词器切词后的单词做进一步过滤和转换,例如,停用词分词过滤器(stop token filter)可以把分词器切分出来的冠词a、介词of等无实际意义的单词直接丢弃,避免它们影响搜索结果。ES中也有几十种内置token filter,在自定义我们的分析器时可以使用。

在自定义分析器时,有如下5个参数可以配置:

参数名参数说明
typeAnalyzer type. Accepts built-in analyzer types. For custom analyzers, use custom or omit this parameter.
tokenizerA built-in or customised tokenizer. (Required)
char_filterAn optional array of built-in or customised character filters.
filterAn optional array of built-in or customised token filters.
position_increment_gapWhen indexing an array of text values, Elasticsearch inserts a fake “gap” between the last term of one value and the first term of the next value to ensure that a phrase query doesn’t match two terms from different array elements. Defaults to 100. See position_increment_gap for more.

下面的mapping自定义了一个分析器,对char_filter、tokenizer、filter分别进行了配置:


PUT my-index-000001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": { 
          "char_filter": [
            "emoticons"
          ],
          "tokenizer": "punctuation",
          "filter": [
            "lowercase",
            "english_stop"
          ]
        }
      },
      "tokenizer": {
        "punctuation": { 
          "type": "pattern",
          "pattern": "[ .,!?]"
        }
      },
      "char_filter": {
        "emoticons": { 
          "type": "mapping",
          "mappings": [
            ":) => _happy_",
            ":( => _sad_"
          ]
        }
      },
      "filter": {
        "english_stop": { 
          "type": "stop",
          "stopwords": "_english_"
        }
      }
    }
  }
}

# 测试效果
POST my-index-000001/_analyze
{
  "analyzer": "my_custom_analyzer",
  "text": "I'm a :) person, and you?"
}
分析器的测试

我们可以使用ES 提供的analyze API 来测试分析器的效果

POST _analyze
{
  "analyzer": "whitespace",
  "text":     "I'm studying ElasticSearch"
}

analyze API也可以测试tokenizer、token filter、character filter的组合效果

POST _analyze
{
  "tokenizer": "standard",
  "filter":  [ "lowercase", "asciifolding" ],
  "text":      "I'm studying ElasticSearch"
}

对于我们在创建索引时自定义的分析器,也可以在指定索引上用analyze API来测试自定义分析器的效果。下面例子在创建mapping时定义了std_folded这个自定分析器,字段my_text使用自定义分析器,我们在指定索引名称后依然可以使用测试api:

## 创建索引,定义了std_folded这个自定分词器
PUT my-index-000001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "std_folded": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "type": "text",
        "analyzer": "std_folded" 
      }
    }
  }
}

## 在索引my-index-000001上测试自定义分词器std_folded的效果
GET my-index-000001/_analyze 
{
  "analyzer": "std_folded", 
  "text":     "Is this déjà vu?"
}

## 在索引my-index-000001上测试指定自定义分词器std_folded的字段my_text的效果
GET my-index-000001/_analyze 
{
  "field": "my_text", 
  "text":  "Is this déjà vu?"
}
中文分词 ik_max

安装方法:在ik_max github 主页下载与ES版本一致的ik_max压缩包,将下载的压缩包解压,将解压后的文件放入ES安装目录/plugins/ik 文件夹下,重新启动ES,就可以使用ik_max提供的分词器ik_max_word和 ik_smart 了。

  • ik_max_word 是细粒度分词 (一般用于索引)

  • ik_smart 粗粒度分词(一般用于搜索)

(可以用analyze API来测试ik_max_word 和 ik_smart的区别)

Normalizer

Normalizer 与 analyzer有点类似但只作用于单个token,所以它不包括tokenizer,只包括部分char filters 和token filters。

只有在单个字符维度处理的filter才能用于Normalizer,比如可以小写转换filter可以使用,但stemming filter不可以。Normalizer支持的filter有:arabic_normalization, asciifolding, bengali_normalization, cjk_width, decimal_digit, elision, german_normalization, hindi_normalization, indic_normalization, lowercase, pattern_replace, persian_normalization, scandinavian_folding, serbian_normalization, sorani_normalization, trim, uppercase.

ES有一个小写转换lowercase内置normalizer,其他形式的Normalizer需要自定义。

自定义Normalizer举例:

UT index
{
  "settings": {
    "analysis": {
      "char_filter": {
        "quote": {
          "type": "mapping",
          "mappings": [
            "« => \"",
            "» => \""
          ]
        }
      },
      "normalizer": {
        "my_normalizer": {
          "type": "custom",
          "char_filter": ["quote"],
          "filter": ["lowercase", "asciifolding"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "foo": {
        "type": "keyword",
        "normalizer": "my_normalizer"
      }
    }
  }
}

其他关于mapping的要点

  • 一旦创建好索引的mapping后,可以继续给mapping添加新的字段,但是旧的字段无法删除和修改

ES__688">ES 搜索

Elasticsearch提供了领域特定语言(Domain Specific Language,DSL)查询语句,使用JSON字符串来定义每个查询请求。(ES查询语句有很多内容,这里只记录一下用过的查询语句,遇到具体场景再去看是否有其他适合的查询用法)

elasticsearch/reference/current/query-dsl-match-all-query.html" rel="nofollow">match all 查询

直接查询索引的全部数据,默认返回前10个文档,每个文档的得分被设置为1.0

GET my-index-000001/_search
{
  "query": {
    "match_all": {
    }
  }
}
GET my-index-000001/_search
{
}

elasticsearch/reference/current/term-level-queries.html" rel="nofollow">精准搜索

查询对象大多数是非text类型字段,直接匹配字段中的完整内容,在这个过程中不会对搜索内容进行文本分析。

  • term 查询,直接返回包含搜索内容的文档,常用来查询索引中某个类型为keyword的文本字段,类似于SQL的“=”查询。
POST my-index-000001/_search
{
 "query": {
   "term": {
     "name.keyword": {
       "value": "张三"
     }
   }
 }
}
  • terms 查询的功能与term 查询的基本一样,只是多术语查询允许在参数中传递多个查询词,被任意一个查询词匹配到的结果都会被搜索出来。

    POST my-index-000001/_search
    {
      "query": {
        "terms": {
          "name.keyword": {
            "value": ["张三", "李四"]
          }
        }
      }
    }
    
  • ids 查询指定主键的文档,实际查询的是文档的_id

    POST my-index-000001/_search
    {
      "query": {
        "ids" : {
          "values" : ["1", "4", "100"]
        }
      }
    }
    
  • exists查询用于筛选某个字段不为空的文档,其作用类似于SQL的“is not null”语句的作用。
    下面的例子查询user字段不为空的数据

    ```
    GET /_search
    {
      "query": {
        "exists": {
          "field": "user"
        }
      }
    }
    ```
    
  • prefix 查询用于搜索某个字段的前缀与搜索内容匹配的文档,前缀查询比较耗费性能,如果是text字段,可以在映射中配置index_prefixes参数,它会把每个分词的前缀字符写入索引,从而大大加快前缀查询的速度

    GET /_search
    {
      "query": {
        "prefix": {
          "user.id": {
            "value": "ki"
          }
        }
      }
    }
    
  • regexp正则查询允许查询内容是正则表达式,它会查询出某个字段符合正则表达式的所有文档(支持的正则语法),它有好几个参数可以指定。

GET /_search
{
  "query": {
    "regexp": {
      "user.id": {
        "value": "k.*y",
        "flags": "ALL",
        "case_insensitive": true,
        "max_determinized_states": 10000,
        "rewrite": "constant_score_blended"
      }
    }
  }
}

  • wildcard 通配符查询允许在查询代码中添加两种通配符,“*”可匹配任意长度的任意字符串,“?”可匹配任意单个字符。
GET /_search
{
  "query": {
    "wildcard": {
      "user.id": {
        "value": "ki*y",
        "boost": 1.0,
        "rewrite": "constant_score_blended"
      }
    }
  }
}

elasticsearch/reference/current/full-text-queries.html" rel="nofollow">全文检索

  • match 查询比较搜索词和每个文档的相似度,只要搜索词能命中文档的分词就会被搜索到,主要用于对指定text类型字段做全文搜索,是很常用的一个查询。
GET /_search
{
  "query": {
    "match": {
      "message": {
        "query": "this is a test"
      }
    }
  }
}

match查询时可以指定一些参数,boost 参数是指相比于检索字段,权重的大小,其默认值为1

{
  "query": {
    "match": {
      "title": {
        "query": "quick brown fox",
        "boost": 2
      }
    }
  }
}

operator 参数用来控制查询内容之间的逻辑关系,是否要全部检索(AND)到或者部分检索(OR)到就可以,默认是OR。

  • match_phrase 会对搜索文本进行文本分析,然后到索引中寻找搜索的每个分词并要求分词相邻,可以通过调整slop参数设置分词出现的最大间隔距离。match_phrase的分词结果必须在被检索字段的分词中都包含,而且**顺序必须相同,**而且默认必须都是连续的(slot=0)。
GET /_search
{
  "query": {
    "match_phrase": {
      "message": {
        "query": "this is a test",
        "slot":1
      }
    }
  }
}

elasticsearch/reference/current/compound-queries.html" rel="nofollow">复合搜索

复合搜索按照一定的方式组织多条不同的搜索语句,有bool、boosting等

bool query

The default query for combining multiple leaf or compound query clauses, as must, should, must_not, or filter clauses. The must and should clauses have their scores combined — the more matching clauses, the better — while the must_not and filter clauses are executed in filter context.

boosting query

Return documents which match a positive query, but reduce the score of documents which also match a negative query.

constant_score query

A query which wraps another query, but executes it in filter context. All matching documents are given the same “constant” _score.

dis_max query

A query which accepts multiple queries, and returns any documents which match any of the query clauses. While the bool query combines the scores from all matching queries, the dis_max query uses the score of the single best- matching query clause.

function_score query

Modify the scores returned by the main query with functions to take into account factors like popularity, recency, distance, or custom algorithms implemented with scripting.

现在主要用到了bool查询,它有四种类型:

OccurDescription
mustThe clause (query) must appear in matching documents and will contribute to the score.
filterThe clause (query) must appear in matching documents. However unlike must the score of the query will be ignored. Filter clauses are executed in filter context, meaning that scoring is ignored and clauses are considered for caching.
shouldThe clause (query) should appear in the matching document.
must_notThe clause (query) must not appear in the matching documents. Clauses are executed in filter context meaning that scoring is ignored and clauses are considered for caching. Because scoring is ignored, a score of 0 for all documents is returned.

使用时可以用minimum_should_match 参数,它是一个文档被召回需要满足的最小匹配的should语句数量,取值有几种不同的写法。如果布尔查询存在must或filter子句,则该值默认为1;否则,该值默认为0。

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user.id" : "kimchy" }
      },
      "filter": {
        "term" : { "tags" : "production" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

ES__945">ES 搜索时的分数是如何计算的

ES的score 是如何计算的

script score 和 function score 获取自定义分数 script score function score

elasticsearch/reference/8.12/search-explain.html" rel="nofollow">解释搜索结果

当我们想知道为什么一个文档在搜索结果中没有出现,或者为什么它出现了,可以使用explain api来显示原因

GET /my-index-000001/_explain/0
{
  "query" : {
    "match" : { "message" : "elasticsearch" }
  }
}

ES__968">python ES 客户端

ES提供了python客户端, 安装:pip install elasticsearch

import json
from elasticsearch import Elasticsearch

query_dsl = {
    "match": {
      "message": {
        "query": "this is a test"
       }
    }
  }

# 建立连接
elastic_search = Elasticsearch(es_host, http_auth=(es_username, es_password), port=es_port)
query = elastic_search.search(index="my-index-000001",
                                    query=query_dsl,
                                    size=20,
                                    request_timeout=1)
# 搜索结果
res = query.get("hits", {}).get("hits", [])

参考资料

  • ES官方文档 ES python客户端文档 Elastic 中国社区官方CSDN博客

  • 书籍《Elasticsearch数据搜索与分析实战》by 王深湛

  • blog ElasticSearch核心知识讲解

  • ES 的排序 :1 2


http://www.niftyadmin.cn/n/5345788.html

相关文章

【ASP.NET Core 基础知识】--数据库连接--使用Entity Framework Core进行数据库访问

一、介绍 Entity Framework Core(简称EF Core)是微软推出的一个轻量级版的Entity Framework,它是一个开源的、跨平台(Windows、Linux和macOS)的对象关系映射(ORM)框架。EF Core 旨在提供快速的…

【MySQL故障】主从延迟越来越大

问题背景 研发执行了一个批量更新数据的操作,操作的表是个宽表,大概有90多个字段,数据量有800多w,但是研发是根据ID按行更新。更新开始后,该集群的主从延迟越来越大。 问题现象 1 从库应用binlog基本无落后&#xf…

Oracle 日常健康脚本

文章目录 摘要常用脚本 摘要 保持 Oracle 数据库的良好健康状况对于系统的可靠性和性能至关重要。本文将介绍一些常用的 Oracle 日常健康脚本,帮助您监控数据库并及时识别潜在的问题,以保证数据库的稳定运行。 常用脚本 1.查询数据库实例和实例级别的…

太阳光模拟器汽车耐老化太阳跟踪聚光户外加速老化试验

1 范围 1.1 本标准适用于以太阳为光源的菲涅耳反射系统来进行汽车外饰材料的加速老化试验。 1.2 本标准规定的设备和方法可用于确定曝露于日光、热和潮湿下的汽车材料的相对耐老化性, 前提是假设试验期间发生的对材料加速老化速率起决定性作用的物理、化学变化机理…

雪花算法 Nginx

雪花算法介绍 SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id 1位,不用。二进制中最高位为1的都是负数,但是生成的id都是正数,所以这个最高位…

由于找不到msvcr120.dll,无法继续执行代码

一、msvcr120.dll作用介绍 msvcr120.dll文件是Microsoft Visual C Redistributable Package的一部分,它是一个动态链接库(DLL)文件。这个文件在Windows操作系统中提供C运行时库支持,包含了大量系统级函数和对象,这些函…

开源项目Git Commit规范与ChangeLog

一,conventional commit(约定式提交) Conventional Commits 是一种用于给提交信息增加人机可读含义的规范。它提供了一组用于创建清晰的提交历史的简单规则。 1.1 作用 自动化生成 CHANGELOG基于提交类型,自动决定语义化的版本变更向项目相关合作开发…

写一份简单的产品说明书:格式和排版建议

现在的市场竞争那么激烈,拥有一份简洁明了的产品说明书可以说是很重要的。产品说明书不仅向用户提供了对产品的详细了解,还能够树立品牌形象,提升用户体验。 | 一、写一份简单的产品说明书—一些建议 1.创意封面设计 一个吸引人的封面设计能…