ElasticSearch(ES) 搜索入门笔记

ES搜索引擎入门+最佳实践() 本篇文章计划给大家介绍什么ES,ES的架构,以及ES搜索入门.我尽量用简单不拖沓的语言给大家介绍,水平有限,时间也有限,各位读者如发现文中有不当之处,请留言指正.ES的全称是Elasticsearch,翻译过来就是弹性搜索,知道就可以,不用纠结这个词的含义,我觉得这个词并不能表述ES的含义.ES并不是传统意义上的数据库,所以不需要用传到的数据库例如Oracle,mysql等数据库与ES进行类比.ES是建立在Lucene(全文搜索)基础上的分布式准实时搜索引擎. 阅读详情

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

环境准备-本地安装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 搜索

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

match all 查询

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

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

精准搜索

查询对象大多数是非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"
      }
    }
  }
}

全文检索

  • 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
      }
    }
  }
}

复合搜索

复合搜索按照一定的方式组织多条不同的搜索语句,有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 搜索时的分数是如何计算的

ES的score 是如何计算的

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

解释搜索结果

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

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

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", [])

参考资料

ElasticSearch——全文搜索引擎 一、为什么需要全文搜索引擎? 首先先来了解一个概念,在我们生活中一般来说有两种数据:结构化数据、非结构化数据 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。 非结构化数据: 非结构化数据又可称为全文数据,指不定长或无固定格式的数据,如邮件,word文档等。 对于结构化数据我们可以直接从数据库查询,而对于非结构化的数据此时就要用到全文检索的方式查询,比如对一个文档或者网页中的内容文本每个词建立一个索引,把这些非结构化的变成结构化的方式然后来查询。 全文搜索引擎百度百科定义:全文搜索引擎是目前 阅读详情

相关推荐

【仿牛客网笔记Elasticsearch,分布式搜索引擎——Elasticsearch入门

Restful是一种设计风格,这种风格规定了前后端应该按照什么标准交互,不同类型的Http的请求的请求的格式是什么样的,请求标准的一种描述。采用集群分布式部署,每一台服务器称为节点,分片是对索引的进一步划分,副本是对分片的备份。7.0的时候废弃掉了。ES中的文档和数据库中的表的一行,文档通常采用的是js结构,js中每一个属性叫字段。支持结构化的数据,非结构化的数据也可以,即各种类型的数据通过它都可以。具体的搜索条件可以通过body提交,通过请求体提交复杂的请求。ES中的类型和数据库中的table表想对应。

xue_hua_c的博客 481

Elasticsearch(三)——Es搜索(简单使用、全文查询、复合查询)、地理位置查询、特殊查询、聚合操作、桶聚合、管道聚合

Elasticsearch(三)——Es搜索(简单使用、全文查询、复合查询)、地理位置查询、特殊查询、聚合操作、桶聚合、管道聚合

qq_41824825的博客 3万+

ε-差分隐私之拉普拉斯噪声机制(定义 + 证明 + 代码)

ε-差分隐私之拉普拉斯噪声机制 差分隐私的描述 1-范式的定义:使用matlab调用函数norm(x, 1) 更多范式见 范式 差分隐私的定义应该满足 拉普拉斯噪声的证明全过程如下: DP方向差分隐私证明是基本入门!!! -拉普拉斯噪声分布代码 Laplace分布的概率密度函数的形式是: 使用python - matplotlib来绘制概率分布图: import matplotlib.pyplot as plt import numpy as np def laplace_fun

毕业才是起点 1万+

全文检索 Elasticsearch(简称es)

全文检索 Elasticsearch 研究 1. ElasticSearch 介绍 1.1 介绍 **Elasticsearch**是一个基于Lucene库的搜索引擎。它提供了一个分布式、支持多租户的全文搜索引擎,具有HTTP Web接口和无模式JSON文档。Elasticsearch是用Java开发的,并在Apache许可证下作为开源软件发布。官方客户端在Java、.NET(C#)、PHP、Py...

CORN的博客 2万+

详解最热门搜索引擎——ES

一、产生背景 ​ 互联网发展早期的时候,对于一般的公司储存的数据量不是那么的大,所以很多公司更倾向于使用数据库去存储和查询数据,如:现在去MySQL中查询数据,大概的查询方式就是:select * from table where filed like “%XXX%”或者其他方式,但是,如果我们在查询的时候没有用到或命中数据库建立的索引话,则会扫描整张表,即便是MySQL做过单表查询能力优化,但是他的极限也只在400万左右,且还会经常出现超时现象,让后为了解决这些问题,。很多公司就开始对数据库进

会编程的小郑 1万+

搜索引擎Elasticsearch入门——学习笔记

官网地址具备下列优势:支持分布式,可水平扩展;提供Restful接口,可被任何语言调用结合kibanaLogstashBeats,是一整套技术栈,被叫做ELK。被广泛应用在日志数据分析、实时监控等领域。

2501_90975132的博客 1172

ES搜索引擎入门笔记

一:安装 参考文档:http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html Elastic 需要 Java 8 环境。如果你的机器还没安装 Java,可以参考这篇文章,注意要保证环境变量JAVA_HOME正确设置。 $ wget https://artifacts.elastic.co/downloads/elasticsearch/e...

qq_32109909的博客 8万+

笔记-Elasticsearch搜索引擎构建入门与实战

读书笔记Elasticsearch搜索引擎构建入门与实战(高印会 编著) 整体来讲 入门没问题,中高级研发可以参考使用

lonsonlee的专栏 2472

Elasticsearch入门学习笔记:快速掌握强大搜索引擎的核心功能

Elasticsearch入门学习笔记:快速掌握强大搜索引擎的核心功能 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在数字化时代,数据搜索和管理的效率显得尤为重要。Elasticsearch入门学习笔记项目应运而生,它提供了一份详尽的入门资料,旨在帮助初学者快速掌握Elasticsearch的基本概念、操作方法和最佳实践。通过这份笔记,你将能够轻松地理解并使用这一分...

gitblog_06774的博客 649

学习笔记ElasticSearch搜索引擎

Elastic表示可伸缩、灵活的意思。结构化数据:按特定结构和组织管理数据,一般表现为二维表结构(比如用户数据,包括用户姓名、年龄、身份证号)。可以保存到关系型数据库(MySQL、Oracle),优点是方便管理和查询,缺点是扩展难非结构化数据:无法用二维表结构表现的数据(如服务器日志、通信记录、文档、报表、视频、图片等)。维度广数据量大,数据存储查询成本大,需要专业人员和大量统计模型进行处理,一般会将这类数据存储于NoSQL数据库中(MongoDB、Redis、Hbase),一般按KV结构进行保存。

qq_45867699的博客 811

Elasticsearch笔记

Elasticsearch笔记 开源搜索Elasticsearch、ELK Stack 和 Kibana 的开发者 | Elastic Elasticsearch简介 全文搜索属于最常见的需求,开源的Elasticsearch是目前全文搜索引擎的首选。它可以快速地存储、搜索和分析海量数据。维基百科、Stack Overflow、Github都采用它。 Elastic的底层是开源库Lucene。但是,你没法直接用Lucene,必须自己写代码去调用它的接口。Elastic是Lucene的封装,提供了REST

厚积薄发 354

elasticsearch--sgg

教学视频结构化数据非结构化数据半结构化数据单台 Elasticsearch 服务器提供服务,往往都有最大的负载能力,超过这个阈值,服务器性能就会大大降低甚至不可用,所以生产环境中,一般都是运行在指定服务器集群中。单台机器存储容量有限单服务器容易出现单点故障,无法实现高可用单服务的并发处理能力有限配置服务器集群时,集群中节点数量没有限制,大于等于 2 个节点就可以看做是集群了。一般出于高性能及高可用方面来考虑集群中节点数量都是 3 个以上总之,集群能提高性能,增加容错。

listening_nq的博客 535

搜索引擎SEO 入门学习摘要笔记

个人在入门学习 SEO 时做的摘要笔记 时不时更新

抓更够 959

Elasticsearch (ES) 搜索引擎: 搜索功能:搜索分页、搜索匹配、全文搜索搜索建议、字段排序

全文搜索一般指对文本(text)类型数据的搜索。与 term、range 等全匹配的结构化搜索不同,全文搜索可以部分匹配。全文搜索首先对搜索词进行分析(分词),根据分析结果再构建出多个子查询。

谢TS的博客 3738

Elasticsearch搜索引擎

笔记

qq_55648724的博客 3046

分布式搜索引擎Elasticsearch(一)

是一款非常强大的开源的分布式的搜索引擎,可以帮助我们从海量数据中快速找到需要的内容。elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK),换句话说 ELK 就是以 Elasticsearch 为核心的技术栈,包括了 kibana、Logsash、Beats。

菜鸟的博客 3164

ElasticSearch搜索详细讲解与操作

总之,每个索引可以被分成多个分片,一个索引也可以被复制0次或多次,一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。mapping是处理数据的范式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其他就是处理es里面的数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。在一个index/type里面,你可以存储任意多的文档。

Stephen_CY666的博客 1009

es搜索方式

搜索了带有“酒店”名称的所有店家,然后通过function中,对品牌为“如家”的酒店进行了weight为10的加权,加权方式为sum,表示在query查询中算出的原有分数中再加上10。没有查询上限,由于他的分页原理时记录上一次最后的值,所以他不支持向前翻页。geo_bounding_box:匹配在指定矩阵内的值,top_left,bottom_rigth,为矩阵的左上角和右下顶点,在查询匹配中可以通过function_score对匹配的结果进行算分,通过算分的值对结果集展示进行重新排序。

hubertbb3的博客 2258

Elasticsearch搜索功能

使用 Elasticsearch 最终目的是为了实现搜索功能,现在先将文档添加到索引中,接下来完成搜索的方法。叶子查询:叶查询子句在特定字段中查找特定值,例如matchterm或range查询。精确查询:根据精确词条值查找数据,一般是查找 keyword、数值、日期、boolean 等类型字段。例如:ids:根据文档 ID 查找文档range:返回包含指定范围内的文档,比如:查询年龄在 10 到 20 岁的学生信息。term:根据精确值(例如价格、产品 ID 或用户名)查找文档。

大一点的小孩 2274

Tesla v100 4张显卡组装机安装vllm和ollama在Ubuntu系统上的安装---AI大模型系统从零开始0032

本文提供Ubuntu22.04系统下vLLM的完整安装指南,适配4×32G Tesla显卡的单机4卡张量并行部署。教程包含:1)硬件要求(Ubuntu22.04、NVIDIA驱动≥535、CUDA12.1+);2)NVIDIA驱动自动安装方法;3)Python3.10虚拟环境配置;4)vLLM官方预编译包一键安装;5)单机4卡启动Qwen3.6-27B模型的完整参数说明(含FP8量化、多进程并行等关键配置)。文末附分布式部署的Ray集群方案参考链接,适用于多机8卡场景。

添柴程序猿的专栏 74

c# sqlserver数据库备份工具源码

1、mssql自动备份,手动备份,自动作业,手动作业处理。二、菜单功能 1、自动备份数据库,手动备份数据库,将备份文件上传至ftp,自动作业处理,手动处理作业等。 2、编辑参数、清空日志。三、注意事项 1、开发环境为Visual Studio 2010,数据库为SqlServer2008,使用.net 4.0开发。

上一篇: 无监督关键词提取算法:TF-IDF、TextRank、RAKE、YAKE、 keyBERT
下一篇: Matryoshka Representation Learning (MRL)-俄罗斯套娃向量表征学习
chencjiajy
博客等级 码龄14年 807粉丝 116原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值