ElasticSearch安装及基本使用

news2025/1/8 19:34:58

文章目录

    • 0. 学习资料
    • 1. 概念
    • 2. 安装
      • ESdocker安装
        • 1. **下载镜像**
        • 2. **创建实例**
        • 3. **浏览器访问:**
        • 4. 测试使用
      • Kibana安装
        • 1. 下载镜像
        • 2. 创建实例
        • 3. 效果
    • 3. 检索
      • _cat
      • 保存
      • 查询
        • 通过id查询
        • 乐观锁操作
      • 更新
      • 删除
      • 批量操作
        • **导入测试数据**
    • 4. 进阶搜索
      • 基本检索
        • 参考文档
        • 基本检索
      • Query DSL
        • 查询和筛选上下文
        • match【匹配查询】
        • match_phrase【短语匹配】
        • multi_match【多字段匹配】
        • Term【精确检索】
        • match的keyword
        • bool【复合查询】
          • must
          • should
          • must_not
          • filter
        • Aggregations(执行聚合)
          • 1. address 中包含 mill 的所有人的年龄分布以及平均年龄,但不显示这些人的详情
          • 2. 按照年龄聚合,并且请求这些年龄段的这些人的平均薪资
          • 3. 复杂:查出所有年龄分布,并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄 段的总体平均薪资
          • 语法参考文档
    • 5. Mapping
      • 介绍
      • 属性类型
      • 映射操作
      • 1. 创建索引映射
      • 2. 给已有映射增加字段
      • 3. 查看映射
      • 4. 更新映射
      • 5. 数据迁移
        • 无type数据迁移
        • 有type数据迁移
      • 6. 数据迁移实例
        • 数据迁移
    • 6. 分词
      • 安装IK分词器
      • 配置远程词库
    • 问题汇总
      • 1. 聚合搜索结果默认只有10条

0. 学习资料

官方文档:[开始搜索|弹性搜索指南 7.5] |弹性的 (elastic.co)

ES(一):ES基本概念和原理简单介绍https://blog.51cto.com/u_14286115/3328651

版本对比:(13条消息) Elasticsearch各个版本重要特性_elasticsearch常用版本_坚持是一种态度的博客-CSDN博客

1. 概念

mysql更适合做数据的持久化处理,增删改查操作。El更适合做数据的检索分析。可以秒级在商品中检索出所需要的信息。

image-20220409202623723

基本概念

  1. Index(数据库) 动词,相当于 MySQL 中的 insert; 名词,相当于 MySQL中的 Database

  2. Type(表) 在 Index(索引)中,可以定义一个或多个类型。 类似于 MySQL 中的 Table;每一种类型的数据放在一起

    注意:7.0版本之后,type类型被移除,7.0检索的时候type可带可不带,8.0不允许带

    移除原因:在同一index中,ES中不同type下名称相同的filed最终在Lucene中的处理方式是一样的,两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个filed,你必须在两个不同的type中定义相同的filed映射。

    去掉type能够使数据存储在独立的index中,这样即使有相同的字段名称也不会出现冲突,就像ElasticSearch出现的第一句话一样“你知道的,为了搜索····”,去掉type就是为了提高ES处理数据的效率。

    查询时,我们可以将所有的type的值都使用_doc 如:查询索引consumer中id为1的数据。 GET /consumer/ _ doc/1

  3. Document(记录) 保存在某个索引(Index)下,某种类型(Type)的一个数据(Document),文档是 JSON 格 式的,Document 相当于Mysql一条记录

  4. mapping(表结构):mapping是对索引库中的索引字段及其数据类型进行定义,ES默认动态创建索引和索引类型的mapping。

  5. 倒排索引

image-20220409203139290

往ES中存储数据的时候,可以使用分词的方式。拿存储1:红海行动和5:特工红海特别探索为例。

  1. 红海行动可以拆分成,红海和行动。将红海行动存储到ES中,将红海和行动这两个词分别存放到ES的倒排索引中。

  2. 特工红海特别探索可以拆分成特工,红海,特别,探索。然后存储到倒排索引中,倒排索引中记录数据在ES中存放的位置。

  3. 查询红海行动时,会将红海行动分词,分成红海和行动,然后去倒排索引中查找

    1. 发现12345和123 都存储的有红海和行动,此时会进行相关性得分。
    2. 其中123 在两个倒排索引中都找到了,因此评分会更高,优先展示123对应的内容,靠后展示45出现的内容。

核心概念

1、分片(shard):
如果我们的索引数据量很大,超过硬件存放单个文件的限制,就会影响查询请求的速度,Es引入了分片技术。一个分片本身就是一个完成的搜索引擎,文档存储在分片中,而分片会被分配到集群中的各个节点中,随着集群的扩大和缩小,ES会自动的将分片在节点之间进行迁移,以保证集群能保持一种平衡。分片有以下特点:

  1. ES的一个索引可以包含多个分片(shard);
  2. 每一个分片(shard)都是一个最小的工作单元,承载部分数据;
  3. 每个shard都是一个lucene实例,有完整的简历索引和处理请求的能力;
  4. 增减节点时,shard会自动在nodes中负载均衡;
  5. 一个文档只能完整的存放在一个shard上
  6. 一个索引中含有shard的数量,默认值为5,在索引创建后这个值是不能被更改的。
  7. 优点:水平分割和扩展我们存放的内容索引;分发和并行跨碎片操作提高性能/吞吐量;
  8. 每一个shard关联的副本分片(replica shard)的数量,默认值为1,这个设置在任何时候都可以修改。

2、副本(replica):

副本(replica shard)就是shard的冗余备份,它的主要作用:

  1. 冗余备份,防止数据丢失;
  2. shard异常时负责容错和负载均衡;

ES的特性:

速度快、易扩展、弹性、灵活、操作简单、多语言客户端、X-Pack、hadoop/spark强强联手、开箱即用。

  1. 分布式:横向扩展非常灵活
  2. 全文检索:基于lucene的强大的全文检索能力;
  3. 近实时搜索和分析:数据进入ES,可达到近实时搜索,还可进行聚合分析
  4. 高可用:容错机制,自动发现新的或失败的节点,重组和重新平衡数据
  5. 模式自由:ES的动态mapping机制可以自动检测数据的结构和类型,创建索引并使数据可搜索。
  6. RESTful API:JSON + HTTP

2. 安装

ESdocker安装

1. 下载镜像

  1. docker pull elasticsearch:7.4.2 存储和检索数据
  2. docker pull kibana:7.4.2 可视化检索数据

2. 创建实例

  1. 创建挂载目录

    1. mkdir -p /mydata/elasticsearch/config

    2. mkdir -p /mydata/elasticsearch/data

    3. echo “http.host: 0.0.0.0” >> /mydata/elasticsearch/config/elasticsearch.yml

      1. echo 代表es可以被远程的任何服务访问,写入es的配置文件。
    4. 创建docker 容器

      1. # 创建配置文件目录
        mkdir -p /opt/docker/mid_elasticsearch_test/config
        
        # 创建数据目录
        mkdir -p /opt/docker/mid_elasticsearch_test/data
        
        # 将/mydata/elasticsearch/文件夹中文件都可读可写
        chmod -R 777 /opt/docker/mid_elasticsearch_test
        
        # 配置任意机器可以访问 elasticsearch
        echo "http.host: 0.0.0.0" >/opt/docker/mid_elasticsearch_test/config/elasticsearch.yml
            
        docker run --name elasticsearch_test  -p 9200:9200 -p 9300:9300 --restart=always \
        -e "discovery.type=single-node" \
        -e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
        -v /opt/docker/mid_elasticsearch_test/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
        -v /opt/docker/mid_elasticsearch_test/data:/usr/share/elasticsearch/data \
        -v /opt/docker/mid_elasticsearch_test/plugins:/usr/share/elasticsearch/plugins \
        -d elasticsearch:7.4.2
            
        # Docker 开机自启,所以 ES 现在也是开机自启
        docker update elasticsearch --restart=always
            
        # 参数解读
        ● -p 9200:9200 -p 9300:9300:向外暴露两个端口,9200用于HTTP REST API请求,9300 ES 在分布式集群状态下 ES 之间的通信端口;
        ● -e  "discovery.type=single-node":es 以单节点运行
        ● -e ES_JAVA_OPTS="-Xms64m -Xmx512m":设置启动占用内存,不设置可能会占用当前系统所有内存,制ES所占用的内存大小,测试服务器使用。
        ● -v:挂载容器中的配置文件、数据文件、插件数据到本机的文件夹;
        ● -d elasticsearch:7.6.2:指定要启动的镜像
            
        # 附:
        如果要修改ES的内存大小,可以停掉ES,删除容器,再重新创建一个容器,因为ES启动的时候进行了目录挂载,因此不会产生数据丢失。
        
  2. 问题:es容器闪退

    1. docker logs esid 查看es容器日志
    2. image-20220411203036153
    3. 无权限访问红色的目录,进入这个目录中查看。
    4. 查看data目录的访问权限
      1. ll 命令
      2. image-20220411203319588
      3. root 用户 可读可写,可执行,但是其他用户只能读和执行权限
      4. 将所有的权限都改成rwx,可读写执行。
        1. 命令:chmod -R 777 /mydata/elasticsearch/
        2. 递归将elasticsearch下的目录都设置为可读可写可执行。
        3. image-20220411203659609
        4. 重启docker 容器即可。

3. 浏览器访问:

  1. image-20220411203910618

4. 测试使用

  1. 查看所有节点信息

    image-20220411204702950

Kibana安装

1. 下载镜像

docker pull kibana:7.4.2 可视化检索数据

2. 创建实例

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://XX.XX.XX:9200 -p 5601:5601  -d kibana:7.4.2

 http://XX.XX.XX:9200 一定改为自己虚拟机的地址,表示要链接的es地址。

3. 效果

image-20230118110151948

3. 检索

查询、更新时,我们可以将所有的type的值都使用_doc 如:查询索引consumer中id为1的数据。 GET /consumer/ _ doc/1

es的所有请求,都封装成了restapi,我们查询数据发送请求即可。

_cat

GET /_ cat/nodes:查看所有节点

GET /_cat/health:查看 es 健康状况

GET / _ cat/master:查看主节点

GET /_cat/indices:查看所有索引 show databases

image-20220411210302421

保存

保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识 .

PUT/POST customer/external/1;在 customer 索引下的 external 类型下保存 1 号数据

es存储的数据都是json对象。

# 已淘汰,执行后会提示[types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
PUT customer/external/1
{
"name": "John Doe"
}
# 最新  以下三种方式均可
POST customer/_create/6   id 为6
{
  "name": "张三"
}

POST customer/_doc/4    id 为 4
{
  "name": "张三"
}

POST customer/_doc      id随机生成
{
  "name": "张三"
}

结果:不管使用_doc还是_create,_type的结果都是_doc
{
  "_index" : "customer",
  "_type" : "_doc",
  "_id" : "10",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 8,
  "_primary_term" : 1
}


PUT 和 POST 都可以,
POST 新增。如果不指定 id,会自动生成 id。指定 id 就会修改这个数据,并新增版本号
PUT 可以新增可以修改。PUT 必须指定 id;由于 PUT 需要指定 id,我们一般都用来做修改
操作,不指定 id 会报错。

put新增:

image-20230119150615899

新增:

image-20230119150637031

查询

通过id查询

GET customer/external/1

淘汰:GET customer/external/1
最新:GET customer/_doc/1  type统一用_doc
    
{ "_index": "customer", //在哪个索引
"_type": "external", //在哪个类型
"_id": "1", //记录 id
"_version": 2, //版本号
"_seq_no": 1, //并发控制字段,每次更新就会+1,用来做乐观锁
"_primary_term": 1, //同上,主分片重新分配,如重启,就会变化
"found": true, "_source": { //真正的内容
"name": "John Doe"
}
}

乐观锁操作

_seq_no 表示乐观锁

假如A,B两个请求都过来了,都要修改同一条数据,如果A将数据修改后,那么_seq_no 会发生变化,由1变为2,B修改的时候,传递一个查询条件,_ seq_no 为1,那么此时B就不发生修改。

假如此时我同时发送两次更新请求:

A:http://39.XX.XX.XX:9200/customer/external/1?if_seq_no=2&if_primary_term=1 修改name = 1

此时_seq_no = “_seq_no”: 3,

B也发送http://39.XX.XX.XX:9200/customer/external/1?if_seq_no=2&if_primary_term=1 请求时,因为seq_no此时已变成3,因此修改不成功。

image-20220411212628115

更新

  1. post带update

    1. POST customer/external/1/_update
      { 
          "doc":{ "name": "John Doew"}
      }
      
    2. post携带update的时候,必须带doc

    3. 更新之后,再次更新时,如果最新的数据和原来的数据一样,那么什么都不进行更新。

  2. 直接使用update

    1. PUT customer/external/1
      { 
          "name": "John Doe"
      }
      
  3. 不同点:

    1. POST 操作会对比源文档数据,如果相同不会有什么操作,文档 version 不增加
      PUT 操作总会将数据重新保存并增加 version 版本;
      带_update 对比元数据如果一样就不进行任何操作。
      看场景;
      对于大并发更新,不带 update;
      对于大并发查询偶尔更新,带 update;对比更新,重新计算分配规则。
      
  4. 更新同时增加属性

    1. POST customer/external/1/_update
      { 
          "doc": { "name": "Jane Doe", "age": 20 }
      }
      PUTPOST 不带_update 也可以
      

删除

删除文档:DELETE customer/external/1

删除索引:DELETE customer
    
没有删除类型的操作。

批量操作

批量添加数据

POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }

语法格式

语法格式:
{ action: { metadata }}
{ request body }
{ action: { metadata }}
{ request body }

混合操作

POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123"} }
{ "doc" : {"title" : "My updated blog post"} }

image-20220411220058663

导入测试数据

G:\ComputerStudy\openitem\gulimallallfiles\课件和文档\高级篇\课件\es文件.txt

POST bank/account/_bulk
curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@/文件路径"

注意:如果是官网下载的json文件,要打开删除最后一个空行,再按回车添加一个空行。官方文件:https://raw.githubusercontent.com/elastic/elasticsearch/7.5/docs/src/test/resources/accounts.json

问题:[使用ElasticSearch在bulk导入json数据时,The bulk request must be terminated by a newline \n]_BackToMeNow的博客-CSDN博客_bulkrequest写入json

4. 进阶搜索

基本检索

参考文档

[查询和筛选上下文|弹性搜索指南 7.5] |弹性的 (elastic.co)

基本检索

ES 支持两种基本方式检索 :

一个是通过使用 REST request URI 发送搜索参数(uri+检索参数)

GET /bank/_search  //查询bank索引下的所有数据
GET bank/_search?q=*&sort=account_number:asc
q=* :查询所有
sort = account_number:asc   排序方式

一个是通过使用 REST request body 来发送它们(uri+请求体)

GET /bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "age": "desc"
    },
    {
      "account_number": "asc"
    }
  ]
}

返回结果:

image-20220412095044584

具体记录:

image-20220412095641874

image-20220412095717906

分页检索

For example, the following request gets hits 10 through 19:

GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ],
  "from": 10,
  "size": 10
}

https://www.elastic.co/guide/en/elasticsearch/reference/7.5/getting-started-search.html)

Query DSL

查询和筛选上下文

相关性分数

默认情况下,Elasticsearch 会按相关性对匹配的搜索结果进行排序 分数,用于衡量每个文档与查询的匹配程度。

相关性分数在查询结果中返回,级别越高,文档越相关。_score

image-20230118143005697

查询上下文

查询子句根据条件来决定文档匹配,还会计算字段中的相关性分数。

筛选上下文

回答查询子句当前记录是否符合,是否达到计算分数要求。

GET /_search
{
  "query": {   该参数指示查询上下文。query
    "bool": {  must两个子句用于查询上下文, 这意味着它们用于对每个文档进行评分比赛。boolmatch
      "must": [
        { "match": { "title":   "Search"        }},
        { "match": { "content": "Elasticsearch" }}
      ],
      "filter": [  该参数指示筛选器上下文。其 and 子句用于筛选器上下文。他们会过滤掉不匹配的文件,但它们不会影响匹配文档的分数。filtertermrange
        { "term":  { "status": "published" }},
        { "range": { "publish_date": { "gte": "2015-01-01" }}}
      ]
    }
  }
}

基本语法格式

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 5,
  "sort": [
    {
      "account_number": {
        "order": "desc"
      },
      "balance": {
      	"order": "asc"
      }
    }
  ]
}

# match_all 查询类型【代表查询所有的所有】,es中可以在query中组合非常多的查询类型完成复杂查询;
# from+size 限定,完成分页功能;从第几条数据开始,每页有多少数据
# sort 排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准;

基本返回结果

语法结构

Elasticsearch 提供了一个可以执行查询的 Json 风格的 DSL(domain-specific language 领域特 定语言)。这个被称为 Query DSL。

查询语句 的典型结构:

image-20220412102022524

如果是针对某个字段:

image-20220412102109747

image-20220412102216410

image-20220412102233573

match【匹配查询】

image-20220412102407551

match_phrase【短语匹配】

image-20220412102515759

multi_match【多字段匹配】

image-20220412102557345

Term【精确检索】

和 match 一样。匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term。

Avoid using the term query for text fields.

避免使用 term 查询文本字段

By default, Elasticsearch changes the values of text fields as part of analysis. This can make finding exact matches for text field values difficult.

默认情况下,Elasticsearch 会通过analysis分词将文本字段的值拆分为一部分,这使精确匹配文本字段的值变得困难。

To search text field values, use the match query instead.

如果要查询文本字段值,请使用 match 查询代替。

使用match

image-20220412105706771

使用term

image-20220412105728335

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "age": {
              "value": "28"
            }
          }
        },
        {
          "match": {
            "address": "990 Mill Road"
          }
        }
      ]
    }
  }
}

match的keyword

普通match

image-20220412105934277

keyword

image-20220412110016703

短语匹配

image-20220412110114125

bool【复合查询】

bool 用来做复合查询: 复合语句可以合并 任何 其它查询语句,包括复合语句,了解这一点是很重要的。这就意味 着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。

匹配与其他布尔组合匹配的文档的查询。类型:BooleanQuery

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 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.must 子句(查询)必须出现在匹配的文档中。
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 for all documents is returned.0 子句(查询)不得出现在匹配项中 文件。

在boolean查询中,must, shouldmust_not 元素都被称为查询子句 。 文档是否符合每个“must”或“should”子句中的标准,决定了文档的“相关性得分”。 得分越高,文档越符合您的搜索条件。 默认情况下,Elasticsearch 返回根据这些相关性得分排序的文档。

“must_not”子句中的条件被视为“过滤器”。 它影响文档是否包含在结果中,但不影响文档的评分方式。还可以显式地指定任意过滤器来包含或排除基于结构化数据的文档。

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

minimum_should_match:最小匹配度,必须紧跟should,用参数指定数字或返回文档的子句百分比必须匹配。

不是很明白,之后需要了的话再细看。

参考文章(18条消息) elasticsearch中minimum_should_match的一些理解_xiao_jun_0820的博客-CSDN博客_minimumnumbershouldmatch

must

必须达到 must 列举的所有条件

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "gender": "M"
          }
        }
      ]
    }
  }
}

should

should:应该达到 should 列举的条件,如果达到**会增加相关文档的评分,并不会改变查询的结果。**如果 query 中只有 should 且只有一种匹配规则,那么 should 的条件就会被作为默认匹配条件而去改变查询结果

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "gender": "M"
          }
        }
      ],
      "should": [
        {
          "match": {
            "address": "lane"
          }
        }
      ]
    }
  }
}
must_not

必须不是指定的情况

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "gender": "M"
          }
        }
      ],
      "should": [
        {
          "match": {
            "address": "lane"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "email": "baluba.com"
          }
        }
      ]
    }
  }
}
address 包含 mill,并且 gender 是 M,如果 address 里面有 lane 最好不过,但是 email 必须不包含 baluba.com

image-20220412103448606

filter

filter 对结果进行过滤,使用方法和must一样,但是没有相关性得分。

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "filter": {
        "range": {
          "balance": {
            "gte": "10000",
            "lte": "20000"
          }
        }
      }
    }
  }
}
# 这里先是查询所有匹配 address 包含 mill 的文档,
# 然后再根据 10000<=balance<=20000 进行过滤查询结果
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "gender": "M"
          }
        }
      ],
      "should": [
        {
          "match": {
            "address": "lane"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "email": "baluba.com"
          }
        }
      ],
      "filter":{
        "range": {
          "age": {
            "gte": 18,
            "lte": 30
          }
        }
      }
    }
  }
}

Aggregations(执行聚合)

**聚合提供了从数据中分组和提取数据的能力。(mysql的聚合函数)**最简单的聚合方法大致等于 SQL GROUP BY 和 SQL 聚合函数。

在 Elasticsearch 中,您有执行搜索返回 hits(命中结果),并且同时返 回聚合结果,把一个响应中的所有 hits(命中结果)分隔开的能力。

这是非常强大且有效的, 您可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用 一次简洁和简化的 API 来避免网络往返。

1. address 中包含 mill 的所有人的年龄分布以及平均年龄,但不显示这些人的详情
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {     //聚合:求年龄的分布情况 。  如年龄38的有多少人。
    "group_by_state": {   //聚合名称
      "terms": {          //分布情况,使用terms
        "field": "age"    //聚合字段
      }
    },
    "ageavg": {  //聚合:求年龄的平均值
      "avg": {          
        "field": "age"
      }
    }
  },
  "size":0  //不显示人的详情。
}

image-20220412145520539

2. 按照年龄聚合,并且请求这些年龄段的这些人的平均薪资
GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age"
      },
      "aggs": {
        "balance_avg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}

image-20220412150220933

3. 复杂:查出所有年龄分布,并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄 段的总体平均薪资

分析:

  1. 年龄分布:进行一次聚合
  2. 年龄段中的M和F:在年龄分布的基础上再进行一次聚合
  3. M和F的平均薪资,记载M和F的基础上再进行一次聚合
  4. 年龄段的总体信息:在年龄分布的基础上,进行一次聚合
GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "genderAgg": {
          "terms": {
            "field": "gender.keyword",  //因为gender是文本类型。具体见下文报错。
            "size": 2
          },
          "aggs": {
            "balanceAvg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "ageAggBalanceAvg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

image-20220412152002694

image-20220412152132213

语法参考文档

[Quick start | Elasticsearch Guide 8.1] | Elastic

image-20220412152415550

5. Mapping

介绍

Maping是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。

比如:使用maping来定义:

  • 哪些字符串属性应该被看做全文本属性(full text fields);
  • 哪些属性包含数字,日期或地理位置;
  • 文档中的所有属性是否都嫩被索引(all 配置);
  • 日期的格式;
  • 自定义映射规则来执行动态添加属性;

查看mapping信息

image-20230118172721998

GET bank/_mapping
{
  "bank" : {
    "mappings" : {
      "properties" : {
        "account_number" : {
          "type" : "long"
        },
        "address" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "age" : {
          "type" : "long"
        },
        "balance" : {
          "type" : "long"
        },
        "city" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "email" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "employer" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "firstname" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "gender" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "lastname" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "state" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

属性类型

[Field datatypes | Elasticsearch Guide 7.5] | Elastic

映射操作

创建映射操作

1. 创建索引映射

创建索引并指定属性的映射规则(相当于新建表并指定字段和字段类型)

PUT /my_index
{
  "mappings": {
    "properties": {
      "age": {
        "type": "integer"
      },
      "email": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      }
    }
  }
}

结果:

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "my_index"
}

2. 给已有映射增加字段

https://www.elastic.co/guide/en/elasticsearch/reference/7.x/explicit-mapping.html#add-field-mapping

PUT /my_index/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false
    }
  }
}

# 这里的 "index": false,表明新增的字段不能被检索。默认是true
# https://www.elastic.co/guide/en/elasticsearch/reference/7.5/mapping-index.html
结果:
{
  "acknowledged" : true
}

3. 查看映射

https://www.elastic.co/guide/en/elasticsearch/reference/7.x/explicit-mapping.html#view-mapping

GET /my_index/_mapping
# 查看某一个字段的映射
GET /my_index/_mapping/field/employee-id

结果:

{
  "my_index" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "email" : {
          "type" : "keyword"
        },
        "employee-id" : {
          "type" : "keyword",
          "index" : false
        },
        "name" : {
          "type" : "text"
        }
      }
    }
  }
}
# index false 表示不能被索引找到

4. 更新映射

https://www.elastic.co/guide/en/elasticsearch/reference/7.x/explicit-mapping.html#update-mapping

对于已经存在的字段映射,我们不能更新。更新必须创建新的索引,进行数据迁移。

Changing an existing field could invalidate data that’s already indexed.

5. 数据迁移

迁移方式分为两种,一种是7和7之后去掉type的情况,一种是包含type 迁移的情况。

无type数据迁移

POST reindex [固定写法]
{
  "source":{
      "index":"twitter"
   },
  "dest":{
      "index":"new_twitters"
   }
}

有type数据迁移

POST reindex [固定写法]
{
  "source":{
      "index":"twitter",
      "twitter":"twitter"
   },
  "dest":{
      "index":"new_twitters"
   }
}

6. 数据迁移实例

对于我们的测试数据,是包含 type 的索引 bank。

现在我们创建新的索引 newbank 并修改一些字段的类型来演示当需要更新映射时的数据迁移操作。

当前bank的文档类型

{
  "bank" : {
    "mappings" : {
      "properties" : {
        "account_number" : {
          "type" : "long"
        },
        "address" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "age" : {
          "type" : "long"
        },
        "balance" : {
          "type" : "long"
        },
        "city" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "email" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "employer" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "firstname" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "gender" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "lastname" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "state" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

创建新索引 newbank 并修改字段类型

数据迁移

POST _reindex
{
  "source": {
    "index": "bank",
    "type": "account"
  },
  "dest": {
    "index": "newbank"
  }
}

结果:

#! Deprecation: [types removal] Specifying types in reindex requests is deprecated.
{
  "took" : 269,
  "timed_out" : false,
  "total" : 1000,
  "updated" : 0,
  "created" : 1000,
  "deleted" : 0,
  "batches" : 1,
  "version_conflicts" : 0,
  "noops" : 0,
  "retries" : {
    "bulk" : 0,
    "search" : 0
  },
  "throttled_millis" : 0,
  "requests_per_second" : -1.0,
  "throttled_until_millis" : 0,
  "failures" : [ ]
}

6. 分词

一个tokenizer(分词器)接收一个字符流,将之分割为独立的tokens(词元,通常是独立的单词),然后输出tokens流。

例如:whitespace tokenizer遇到空白字符时分割文本。它会将文本“Quick brown fox!”分割为[Quick,brown,fox!]。

该tokenizer(分词器)还负责记录各个terms(词条)的顺序或position位置(用于phrase短语和word proximity词近邻查询),以及term(词条)所代表的原始word(单词)的start(起始)和end(结束)的character offsets(字符串偏移量)(用于高亮显示搜索的内容)。

elasticsearch提供了很多内置的分词器,可以用来构建custom analyzers(自定义分词器)。

POST _analyze
{
  "analyzer": "standard",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
结果:
{
  "tokens" : [
    {
      "token" : "the",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "2",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<NUM>",
      "position" : 1
    },
    {
      "token" : "quick",
      "start_offset" : 6,
      "end_offset" : 11,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}

默认的分词器一般都是针对于英文,对于中文我们需要安装额外的分词器来进行分词。

没有中文分词器

GET _analyze
{
   "analyzer": "ik_max_word", 
    "text":"蔡徐坤"
}

image-20230119095034681

安装IK分词器

# 进入挂载的插件目录 /opt/docker/mid_elasticsearch_test/plugins
cd /opt/docker/mid_elasticsearch_test/plugins

# 安装 wget 下载工具
 yum install -y wget

# 下载对应版本的 IK 分词器(这里是7.4.2)
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2

# 进入容器内部
docker exec -it elasticsearch /bin/bash

# 查看 es 插件目录
ls /usr/share/elasticsearch/plugins

# 可以看到 elasticsearch-analysis-ik-7.4.2.zip

配置远程词库

这里对于默认词库中没有的词,不会有词语的组合,所以我们可以通过配置自定义词库或远程词库来实现对词库的扩展。

安装nginx

# 创建初始nginx容器,目的复制默认配置
docker run -p 80:80 --name nginx -d nginx:1.10
# 将容器呢欸文件拷贝到当前目录:
docker cp nginx:/etc/nginx .
# 修改文件名称nginx 为conf,并移动到/opt/docker/mid_nginx_test/nginx目录下
mv nginx conf
mv conf/ /opt/docker/mid_nginx_test
# 直接删除旧的容器
docker rm -f nginx
# 启动新的容器
docker run -p 80:80 --name nginx-test -v /opt/docker/mid_nginx_test/nginx/html:/usr/share/nginx/html -v /opt/docker/mid_nginx_test/nginx/logs:/var/log/nginx -v /opt/docker/mid_nginx_test/nginx/conf:/etc/nginx -d nginx:1.10

配置远程词库

进入:vi /opt/docker/mid_elasticsearch_test/plugins/ik/config/IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 -->
        <entry key="ext_dict"></entry>
         <!--用户可以在这里配置自己的扩展停止词字典-->
        <entry key="ext_stopwords"></entry>
        <!--用户可以在这里配置远程扩展字典 -->
        <!-- <entry key="remote_ext_dict">words_location</entry> -->
 <entry key="remote_ext_dict">http://82.157.236.113/fenci.txt</entry>
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

重启es:docker restart elasticsearch

测试分词效果:

GET _analyze
{
   "analyzer": "ik_max_word", 
    "text":"蔡徐坤"
}
结果:
{
  "tokens" : [
    {
      "token" : "蔡徐坤",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    }
  ]
}

问题汇总

1. 聚合搜索结果默认只有10条

解决方案:在聚合的terms中添加size字段。

GET bank/_search
{
  "size":0,  # 只返回聚合字段age的信息
  "aggs": {     
    "group_by_age": {  
      "terms": {         
        "field": "age",    
        "size":100
      }
    }
  }
}

因为es中数据量巨大,因此必须通过size限制,进而防止OOM。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/172596.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将数据从Java Bean复制到另一个Java Bean

JavaBean复制的几种方式1&#xff1a;概述在实际编程过程中&#xff0c;我们常常要遇到这种情况&#xff1a;有一个对象A&#xff0c;在某一时刻A中已经包含了一些有效值&#xff0c;此时可能 会需要一个和A完全相同新对象B&#xff0c;并且此后对B任何改动都不会影响到A中的值…

P2T: Pyramid Pooling T ransformer for Scene Understanding

论文链接&#xff1a; https://arxiv.org/abs/2106.12011 中文版本&#xff1a; https://mmcheng.net/wp-content/uploads/2022/08/22PAMI_P2T_CN.pdf 代码链接&#xff1a; https://github.com/yuhuan-wu/P2T P2T: Pyramid Pooling T ransformer for Scene Understanding一、摘…

2023年网络安全比赛--JavaScript安全绕过中职组(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 1.使用渗透机场景kali中工具扫描服务器,将服务器上apache版本号作为flag提交; 2.使用渗透机场景windows7访问服务其场景中的网站(网站路径为IP/javascript),找到网站首页中flag并提交; 3.使用渗透机场景windows7根据第二题的…

2. 拍照的基础知识

1. 单反相机的全称为单镜头反光相机 单反相机的原理就体现在“单”和“反”上&#xff0c;单字就是单镜头&#xff0c;就是说单反相机只能安装一个镜头&#xff0c;光线或是影像通过单反镜头进行来取景的。 对于“反”来说就是相机系统内部有一个反光板。光线通过单反镜头投射…

你应该知道的 7 个最受欢迎的 Python 机器学习库

2023年你应该知道的 7 个最受欢迎的 Python 机器学习库 33/100 发布文章 weixin_38037405 未选择任何文件 new 有一句谚语“你不必重新发明轮子”&#xff0c;工具库就是最好的例子。它可以帮助您以简单的方式编写复杂且耗时的功能。在我看来&#xff0c;一个好的项目会使用一些…

LeetCode分类刷题----字符串篇

字符串字符串1.反转字符串344.反转字符串541.反转字符串||2.替换空格剑指offer05.替换空格3.翻转字符串里的单词151.反转字符串里的单词4.左旋转字符串剑指 Offer 58 - II. 左旋转字符串5.实现strStr函数()28.实现strStr()函数6.重复的子字符串459.重复的子字符串字符串 1.反转…

YOLOv1学习笔记

来源&#xff1a;投稿 作者&#xff1a;ΔU 编辑&#xff1a;学姐 论文笔记 《You Only Look Once:Unifified, Real-Time Object Detection》 Joseph Redmon∗ , Santosh Divvala∗†, Ross Girshick , Ali Farhadi∗† University of Washington∗ , Allen Institute for A…

【JavaGuide面试总结】计算机网络·上

【JavaGuide面试总结】计算机网络上1.OSI 七层模型是什么&#xff1f;每一层的作用是什么&#xff1f;2.TCP/IP 四层模型是什么&#xff1f;每一层的作用是什么&#xff1f;应用层传输层网络层网络接口层3.应用层有哪些常见的协议&#xff1f;4.为什么网络要分层&#xff1f;5.…

数据分析方法与模型

文章目录1 数据分析1.1 占比分析1.2 趋势分析1.3 对比分析1.4 象限分析1.5 排名分析1.6 维度分析2 分析模型2.1 费米问题-大致估算2.2 七问分析法-思考角度的拓展2.3 互联网通用模型AARRR、八角分析法2.3.1 AARRR2.3.2 游戏化用户增长策略-八角模型本文来源&#xff0c;为接地气…

基于RMI技术的数据库操作中间件设计 综合实践报告

前言 1.1 实践目的和要求 为了将理论用于实践,巩固所学知识,提高自己发现问题并用所学知识分析问题和解决问题的能力,锻炼自己的工作能力,适应社会能力,自我管理能力,了解目前软件的应用情况,需求情况,发展方向及前景。 要求&#xff1a; 要求在实习过程中认真学习技术知…

[疑难杂症2023-002]不就是Move一个文件吗,怎么会有这么多坑呢?

本文由Markdown语法编辑器编辑完成&#xff0e; 1. 前言: 近期在项目中遇到一个需求&#xff0e; 背景是&#xff0c;在一个QT封装的C/S架构的软件中&#xff0c;一个报告的预览页面&#xff0c;是由QT封装了QWebWidget, 里面放着一个网页&#xff0e;这个网页通过调用一定的…

论文解读 TOOD: Task-aligned One-stage Object Detection

github: https://github.com/fcjian/TOOD paper: https://arxiv.org/pdf/2108.07755.pdf 关键点 思考起点 指出传统one-stage算法在在优化目标分类和定位问题中的不足&#xff08;DecoupledHead分离了分类任务和回归任务[yolox表示解耦这是优点&#xff0c;yolo1-5都是使用y…

[oeasy]python0054_三引号_原样显示字符串_triple_quoted

三引号 回忆上次内容 \ 首先是转义字符 可以 和别的字符 构成转义序列 \a是 ␇ (bell),\b 退回一格\t 水平制表符\v、\f LineFeed\\ 输出 \\" 输出 "\ 输出 \xhh 通过 16 进制数值转义\nnn 通过 8 进制数值转义\ 还是 续行字符 放在 行尾可以让 下一行和本行 连成一…

Linux2

4.Linux的文件系统4.1.linux中所有的一切都是文件万事万物皆文件windows是盘符&#xff0c;linux是树windows是\&#xff08;翘&#xff09;linux是/4.2.查找文件方式&#xff1a;1. 绝对路径 有/2. 相对路径 4.3.挂载&#xff1a;执行挂载命令&#xff1a;mount 设备文件名 挂…

CentOS 安装 MinIO Server

1) 下载 MinIO 服务 wget https://dl.min.io/server/minio/release/linux-amd64/minio chmod x minio sudo mv minio /usr/local/bin/ 2) 创建systemd服务文件 sudo vim /etc/systemd/system/minio.service [Unit] DescriptionMinIO Documentationhttps:…

C语言文件操作(2) “流”的拓展介绍

tips 1. 打开一个文件 -> 内存里面就会创建一个对应关联的文件信息区 -> 文件信息区其实就是一个FILE类型的结构体 -> 各个结构体成员记录了该文件的种种信息 -> 结构体(文件信息区)由FILE* 结构体指针来维护 -> 有了指针&#xff0c;一切都好说了 2. 使用文…

文献阅读(45)——使用自监督学习对AMD分类

使用自监督学习对AMD分类 文章目录使用自监督学习对AMD分类一、简介二、先验知识三、文章核心内容四、使用方法1. 非参数化实例歧视&#xff08;中文翻译过来总是奇奇怪怪&#xff0c;其实就是NPID&#xff09;a 挑战b 解决方案c 转化&#xff01;2. 数据集3. 数据预处理五、结…

Python之拉盖尔多项式

文章目录拉盖尔多项式简介微分与积分求根和反演采样和拟合拉盖尔多项式简介 拉盖尔多项式是拉盖尔方程的标准解&#xff0c;但其更著名的应用是薛定谔方程在解氢原子的时候&#xff0c;其径向函数最后要乘上一个Ln−l−12l1(2rnaμ)L^{2l1}_{n-l-1}(\frac{2r}{na_\mu})Ln−l−…

TCP/IP应用层常见协议总结

TCP/IP应用层常见协议总结1.HTTP:超文本传输协议2.SMTP:简单邮件传输(发送)协议3.POP3/IMAP:邮件接收的协议4.FTP:文件传输协议5.Telnet:远程登陆协议6.SSH:安全的网络传输协议1.HTTP:超文本传输协议 超文本传输协议 主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我…

浏览器的通信能力

用户代理 浏览器可以代替用户完成http请求&#xff0c;代替用户解析响应结果&#xff0c;所以我们称之为&#xff1a;用户代理 user agent 在网络层面&#xff0c;对于前端开发者&#xff0c;必须要知道浏览器拥有的两大核心能力 自动发出请求的能力自动解析响应的能力 自动…