elasticsearch学习

为什么要用

安装

安装es

  1. java需要java环境(es7自带),关闭防火墙sudo systemctl stop firewalld
  2. 创建用户设置密码,es不允许root用户启动useradd es,passwd es
  3. 切换到es用户su es && cd /home/es
  4. 下载wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.2-linux-x86_64.tar.gz
  5. 解压tar -zxvf elasticsearch-7.17.2-linux-x86_64.tar.gz && cd elasticsearch-7.17.2
  6. 修改两处配置项(方便在主机访问,不改也能启动):vi config/elasticsearch.yml``network.host: 0.0.0.0``discovery.seed_hosts: ["10.211.55.26"]
  7. 启动nohup ./bin/elasticsearch &,curl -v 127.0.0.1:9200返回
  8. 启动可能遇到的问题
    1. max file descriptors [4096] for elasticsearch process likely too low, increase to at least [65536]设置最大打开句柄和允许生成的线程数
      • 解决方案:sudo vi /etc/security/limits.conf
      # soft警告值,hard最大值,nproc创建线程数量,nofile 每个进程打开的文件数量限制
      * soft nofile 65536 
      * hard nofile 13107
      
      重新登陆 查看是否生效ulimit -H -n
    2. max number of threads [1024] for user [es] likely too low, increase to at least [4096]普通用户可以创建的最大线程数
      • 解决方案:sudo vi /etc/security/limits.d/20-nproc.conf
      * soft nproc 4096
      
    3. max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
      • 解决方案:sudo vim /etc/sysctl.conf vm.max_map_count=262144

安装图形化界面kibana

  1. 下载https://artifacts.elastic.co/downloads/kibana/kibana-7.17.2-darwin-x86_64.tar.gz
  2. 解压tar -zxvf kibana-7.17.2-darwin-x86_64.tar.gz
  3. 配置vi kibana-7.17.2-darwin-x86_64/config/kibana.yml ``server.host: "10.211.55.26"``elasticsearch.hosts: ["http://10.211.55.26:9200"]
  4. 访问http://10.211.55.26:5601

安装中文分词器

  1. 根据安装的es版本进行下载https://github.com/medcl/elasticsearch-analysis-ik/releases
  2. 解压zip包unzip elasticsearch-analysis-ik-7.17.2.zip -d elasticsearch-7.17.2/plugins/ik
  3. 重启es

安装elasticsearch-head

  1. 主机有nodejs环境
  2. 下载源代码git clone https://github.com/mobz/elasticsearch-head.git && cd elasticsearch-head
  3. 安装依赖npm install
  4. 修改配置vi _site/app.js
  5. 启动npm run start
  6. 浏览器访问http://10.211.55.26:9100/
  7. 使用,支持查询索引分片集群健康情况,普通搜索和dsl查询

数据管理

  1. index,type,document,field
关系型数据库databasetablerowcolumn
esindextypedocmentfield
  1. 基础操作
    1. 操作索引
      1. 创建索引官网介绍
      PUT /test
      {
        "settings": {
          // 指定分片_cat/indices?v查看分片副本状态
          "number_of_shards": 5,
          // 指定副本 每个分片的副本数
          "number_of_replicas": 1
        },
        // 起别名 多对多,写入只能有一个
        "aliases": {
          "testName": {}
        },
        //指定每个field的数据结构,es6可以指定type es7默认_doc
        "mappings": {
          "properties": {
            "name": {
              "type": "text"
            },
            "age": {
              "type": "short"
            }
          }
        }
      }
      
      1. 查询索引
      //使用索引名称或别名
      GET /testName
      GET /test
      
      1. 删除索引
      // 删除索引 使用索引名称或别名
      DELETE /test
      DELETE /testName
      
    2. 操作文档
      1. 添加或修改
      // index/type/id
      PUT /test/_doc/1
      
      1. 查询文档
      get /test/_doc/1
      
      1. 删除文档
      delete /test/_doc/1
      
    3. 文档查询
      1. 查询type中所有文档get /test/_doc/_search
      2. 等值查询get /index/type/_search?q=field:value
      3. 范围查询:get /test/_doc/_search?q=age[12 TO 14]``get /test/_doc/_search?q=age:<=12
      4. 多id查询
      get /test/_doc/_mget
      {
        "ids":["1","2"]
      }
      
      1. 分页查询跳过多少数据返回多少数据 get /test/_doc/_search?from=1&size=2
      2. 指定返回的字段get /test/_doc/_search?_source=name,age
      3. 字段排序:get /test/_doc/_search?sort=age:asc
  2. _mget使用
get /test/_doc/_mget
{
  "docs": [
    {
      //index,id必填index,type可在url中
      "_index": "test",
      "_type": "_doc",
      "_id": "1",
      "_source":["name","age"]
    }
  ]
}
  1. _buik使用,上一行为操作对象与操作,下一行为参数
POST _bulk
{"create": {"_index": "test","_type": "_doc"}}
{"name": "test1"}
{"create": {"_index": "test","_type": "_doc","_id":"6"}}
{"name": "test1"}
{"update":{"_index":"test","_type":"_doc","_id":"5"}}
{"doc":{"name":"test2"}}
{"index":{"_index":"test","_type":"_doc","_id":"5"}}
{"name":"test3"}
{"delete":{"_index":"test","_type":"_doc","_id":"6"}}
  1. dsl语法:文档入es进行分词,这里的查询都是对分词后的关键词进行查询,官方文档
    1. 无条件查询
    GET /test/_search
    {
      "query": {
        "match_all": {}
      }
    }
    
    1. 模糊查询与精准查询
      1. match
        GET /test/_search
         {
         //select * from test_name_keyword where keyword ='河' or keyword='南' 对test索引中的name字段的关键词进行搜索,这里会对查询结果也进行分词
           "query": {
             "match": {
               //默认为or
               "name": "河南"
             }
           }
         }
        
        GET /test/_search
         {
           "query": {
             //select * from test_name_keyword where keyword ='河' and keyword='南'
             "match": {
              "name": {
                "query": "河南",
                "operator": "and"
              }
             }
           }
         }
        
      2. prefix
      GET /test/_search
      {
      //select * from test_name_keyword where keyword  like '北%'      这里不会对查询的参数也进行分词
        "query": {
          "prefix": {
            //默认为or
            "name": "北"
          }
        }
      }
      
      1. regexp
      GET /test/_search
      {
        "query": {
          //select * from test_name_keyword where keyword regexp '河|南'
          "regexp": {
           "name":"河|南"
          }
        }
      }
      
      1. term
      GET /test/_search
      {
        "query": {
          //select * from test_name_keyword where keyword = '河南' 不会对搜索参数进行分词
          "term": {
           "name":"河南"
          }
        }
      }
      
      1. terms
      GET /test/_search
      {
      //select * from test_name_keyword where keyword  ='hello' or keyword ='world'      这里不会对查询的参数也进行分词
        "query": {
          "terms": {
            "name": ["hello","world"]
          }
        }
      }
      
      1. 范围查询 gte大于等于,lte小于等于,gt大于,lt小于
      GET /test/_search
      {
        "query": {
          "range": {
            "age": {
              "gte": 10,
              "lte": 20
            }
          }
        }
      }
      
      1. exists:
      GET /test/_search
      {
        //返回含有name字段的文档
        "query": {
          "exists": {
            "field": "name"
          }
        }
      }
      
      1. ids
      GET /test/_search
      {
        "query": {
          "ids": {
            "values": [
              "PqIRN4ABbtnWqjekU16e"
            ]
          }
        }
      }
      
      1. query_string:和match类似不用指定字段名称
      2. match_phase: 会对参数分词但必须包含所有分词且顺序固定
      GET /test/_search
      {
        "query": {
          "match_phrase": {
            "name": "hello world"
          }
        }
      }
      
    2. 多条件
      1. bool:
        1. must:必须符合条件,里面的关系是and
        2. should:or
        3. must not 不能有,不计分会缓存
        4. filter: 和must一样,and关系,不计分会缓存
        GET /test/_search
        {
          "query": {
            "bool": {
              "filter": [
                {
                  "term": {
                    "name": "hello"
                  }
                }
              ],
              "must_not": [
                {
                  "range": {
                    "age": {
                      "gt": 15
                    }
                  }
                }]
            }
          }
        }
        
      2. constant_score恒分查询:直接修改查询结果的分
      GET /test/_search
      {
        "query": {
          "constant_score": {
            "filter": {
              "term": {
                "name": "hello"
              }
            },
            "boost": 0.1
          }
        }
      }
      
  2. 基础类型
    1. 字符串:text和keyword
      • 区别:text会被分词不能用来排序和聚合,keyword不会被分词可以用来过滤排序聚合
    2. 数值: long,integer,short,byte,double,float
    3. 日期:date
    4. 布尔:boolean
  3. 动态映射与静态映射
    • 动态映射:不需要指定指定字段名称与类型,插入第一条数据时自定映射
    • 静态映射:事先指定好字段名称与类型,分词器,后续为指定的字段还是会动态映射
  4. 修改mapping:新建一个,老的传过去,删除老的,新的起个别名
PUT /test1
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "age": {
        "type": "text",
        "index": false
      }
    }
  }
}
POST _reindex
{
  "source": {
    "index": "test"
  },
  "dest": {
    "index": "test1"
  }
}
DELETE test
PUT /test1/_alias/test

集群

#保持一致 默认elasticsearch
#cluster.name: my-application
#每个节点名称不同
node.name: node1
network.host: 0.0.0.0
# 上下保持顺序
discovery.seed_hosts: ["10.211.55.26","10.211.55.29"]
cluster.initial_master_nodes: ["node1", "node2"]

查询集群状态

GET _cat/health?v
GET _cat/nodes?v

es乐观并发控制

POST /test/_doc/1/?if_primary_term=1&if_seq_no=3
{
  "name":"test",
  "age":1
}

es架构

  1. 节点类型
    1. master节点:es启动后会通过Zen Discovery机制找到集群中的其他节点并建立连接,并从候选主节点中选举出一个主节点,master节点主要负责管理索引(创建删除索引),分配分片,维护元数据,管理集群节点状态,不负责数据写入和查询
    2. datanode:数据写入查询

重要工作流程

写入流程

  1. 每个节点都是协调节点,根据文档的id计算路由到哪个分片,算法默认是文档id%分片数
  2. 主分片写入,写入完成后副本写入,逐级返回结构
  3. 具体详细过程可参考ElasticSearch写入流程详解,深入理解Elasticsearch写入过程

检索流程

  1. 每个节点都是协调节点,收到请求后将查询请求广播到各个数据节点
  2. 每个数据节点进行查询,将符合条件的数据放在一个优先队列,将这些数据的文档id,节点信息,分片信息返回给协调节点
  3. 协调节点将结果进行汇总,排序,分页等
  4. 协调节点想包含这些文档id的分片发送get请求,对应的分片将数据返回给协调节点
  5. 协调节点进行返回给客户端

准实时索引实现

当数据写入到es的分片中时会首先写入到memory buffer中,同时会记录translog,将memory buffer的数据每1秒钟刷新到File system cache,删除memory buffer,每30分钟同步到磁盘中删除

java api使用

    // <dependency>-->
    //     <groupId>org.elasticsearch.client</groupId>-->
    //     <artifactId>elasticsearch-rest-high-level-client</artifactId>-->
    //     <version>7.17.2</version>-->
    // </dependency>
    // RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost("10.211.55.26", 9200, "http"),
    //         new HttpHost("10.211.55.29", 9200, "http"),
    //         new HttpHost("10.211.55.30", 9200, "http"));
    // RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder);
    // IndexRequest indexRequest = new IndexRequest("user");
    // User user = new User();
    // user.setUserId("1");
    // user.setUserName("测试");
    // user.setAge(1);
    // indexRequest.id(user.getUserId());
    // indexRequest.source(JSON.toJSONString(user), XContentType.JSON);
    // IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    // System.out.println(indexResponse.getResult());

    // <dependency>
    //     <groupId>co.elastic.clients</groupId>
    //     <artifactId>elasticsearch-java</artifactId>
    //     <version>7.17.2</version>
    // </dependency>
    RestClient restClient = RestClient.builder(new HttpHost("10.211.55.26", 9200, "http"),
            new HttpHost("10.211.55.29", 9200, "http"),
            new HttpHost("10.211.55.30", 9200, "http")).build();
    RestClientTransport restClientTransport = new RestClientTransport(restClient, new JacksonJsonpMapper());
    ElasticsearchClient elasticsearchClient = new ElasticsearchClient(restClientTransport);
    //创建索引
    // CreateIndexResponse createIndexResponse = elasticsearchClient.indices().create(builder -> builder.index("user"));
    // 插入doc
    // Map<String, Object> map = new HashMap<>();
    // map.put("userName", "test");
    // map.put("age", "12");
    // map.put("id", 1);
    // elasticsearchClient.create(CreateRequest.of(e -> e.index("user").id("1").document(map)));
    SearchRequest searchRequest = SearchRequest.of(builder -> builder.index("user").query(builder1 -> builder1.term(builder2 -> builder2.field("userName").value("test"))));
    SearchResponse<Object> search = elasticsearchClient.search(searchRequest, Object.class);
    ArrayList<Object> objects = new ArrayList<>();
    if (search.hits() != null) {
        List<Hit<Object>> list = search.hits().hits();
        for (Hit<Object> hit :
                list) {
            Object t = (Object) hit.source();
            objects.add(t);
        }
    }
    System.out.println(objects);
}

参考文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jamin_Ye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值