一、ES 相关介绍

1.ES是一个使用Java语言并且基于Lucene编写的搜索引擎框架,提供了分布式的全文搜索功能,还提供了一个统一的基于RESTful风格的Web接口,官方客户端也对多种语言提供了相应的API。

2.Lucene:它本身就是一个搜索引擎的底层。属于Apache的一个顶级项目,和Solr一样属于核心搜索库

3.分布式:ES主要是为了突出自身的(横向)高扩展能力

4.全文检索:将一段词语进行分词,并且将分出的单个词语统一的放到一个分词库中;在搜索时,根据关键字去分词库中检索,找到匹配的内容。(倒排索引)

5.RESTful风格的Web接口:操作ES很简单,只需要发送一个http请求,并且根据请求方式不同和携带参数的而不同,执行相应的功能。

6.应用广泛:Github.com, Wiki,Goldman用ES维护日均近10TB的数据。

二、ElasticSearch和Solr之间的区别

(1).查询效率:Solr查询死数据(即数据不可改变,不可多或少)时,检索速度优先于ES;若数据实时改变时,Solr的查询效率将大幅降低,而ES检索效率几乎不变

(2).搭建集群:Solr搭建基于Zookeeper来帮助管理,ES本身支持集群的搭建,不需要第三方介入

(3).文档社区:Solr的社区开始十分火爆,但针对国内的文档并不多;在ES出现之后,ES的相关社区火爆程度直线上升,ES文档也相对更健全

(4).云计算和大数据:ES针对现在的主流技术(云计算和大数据)的支持和处理相对特别友好。

概念说明:

倒排索引:大致将ES服务分为两块(分词库和数据区),将存放的数据以一定的方式进行分词,并且将分词的内容存放到一个单独的分词库中

<1>.当用户查询数据时,会先将用户的查询关键词进行分词

<2>.然后去分词库中匹配内容,最终得到数据的索引标识

<3>.根据索引标识去存放数据区拉取指定的数据

三、ES的安装指引

1.安装ES & Kibana (ES 的可视化界面)

说明:具体下载安装指南此文参考文献:https://www.jianshu.com/p/05e203ea51af

(1).拉取ES镜像

docker pull docker.elastic.co/elasticsearch/elasticsearch:7.5.0

(2).单节点运行ES

docker run -d --restart=always -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.5.0

 (3.1).多节点运行ES

创建一个docker-compose.yml 文件

version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
    container_name: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
    container_name: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic

volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local

networks:
  elastic:
    driver: bridge
  • 节点 es01 监听 localhost:9200, es02 和 es03 类似
  • 数据卷 data01,data02,data03。可以持久化
  • 启动:docker-compose up
  • 停止:docker-compose down
  • 停止并删除数据卷:docker-compose down -v
  • 查看节点是否启动

  curl -X GET "localhost:9200/_cat/nodes?v&pretty"

(3.2)设置vm.max_map_count

 grep vm.max_map_count /etc/sysctl.conf  vm.max_map_count=262144  sysctl -w vm.max_map_count=262144

(4)安装Kibana
docker pull docker.elastic.co/kibana/kibana:7.5.0

(5)设置kibana

docker run --link YOUR_ELASTICSEARCH_CONTAINER_NAME_OR_ID:elasticsearch -p 5601:5601 {docker-repo}:{version}
docker run -d --restart=always --link a72adb9bf49a:elasticsearch -p 5601:5601 docker.elastic.co/kibana/kibana:7.5.0

(6).拉取logstash镜像
docker pull docker.elastic.co/logstash/logstash:7.5.0

(7).安装elasticsearch插件监控管理
docker pull mobz/elasticsearch-head:5
docker run -d -p 9100:9100 docker.io/mobz/elasticsearch-head:5
(8).安装ik分词器
从github项目中查找ik分词器:
https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.0/elasticsearch-analysis-ik-7.5.0.zip
<1>.先通过docker进入到es容器内部:docker exec -it 容器id bash
<2>.容器内部切换目录并执行安装:cd bin/
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.0/elasticsearch-analysis-ik-7.5.0.zip
<3>.说明:国内网站下载比较慢,下载安装的kibana和ik分词器的版本都要和elasticsearch保持一致。

(9).重启ES通过执行docker命令重启es: docker restart 容器id

具体实现效果如下所示:

es java es Java框架_docker

四、ES的数据结构

1.ES服务和MySQL数据库之间的比较:
ES服务:会搭建集群,可以创建多个索引,每个索引可以被分成5片存储,且每个分片都会存在至少一个备份分片;
备份分片默认不会帮助检索数据,只有当ES检索压力特别大的情况下,备份分片才会帮助检索数据;
备份分片必须存放在不同的服务器中;
对索引进行分片,可以提高检索数据的效率,存储数据容量得到提升。
ES 5.x版本中,一个索引index可以创建多个type;
ES 6.x版本中,一个索引index可以创建一个type;
ES 7.x版本中,一个索引index没有type。

ES 服务的index类似于MySQL的数据库;
ES 服务的type类似于MySQL的table;
ES 服务的document类似于MySQL的一行数据存在多个列。

2.常见数据类型
字符串类型 :
  text:一般被用于全文检索,将当前Field进行分词
  keyword:意旨关键字,当前Field不会被分词
数值类型:
  long
  integer
  short
  byte
  double
  float
  half_float:表示精度比float小一半
  scaled_float:根据一个long和scaled来表达一个浮点型 (例如:long-345 scaled-100 即表示3.45)
时间类型:date (针对时间类型指定具体的格式)
布尔类型:boolean
二进制类型:binary (暂时支持64位编码字符集)
范围类型:long_range (赋值时,无序指定具体内容,只需要存储一个范围即可)
经纬度类型:geo_point (用来存储经纬度)
ip类型:可以存储ipv4或ipv6
如果对其他数据类型感兴趣,可以参考如下官网进行学习
具体参考文献:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/mapping.html#field-datatypes

五、操作ES的RESTful语法

1.GET请求

(1).查询索引信息:http://ip:port/index

(2).查询指定文档信息:http://ip/port/index/type/doc_id

2.POST请求

(1).查询指定文档 (可在请求体中添加json字符串代替查询条件):http://ip:port/index/type/_search

(2).查询指定文档 (可在请求体中指定json字符串代替修改条件):http://ip/port/index/type/doc_id/_update

3.PUT请求

(1).创建索引 (需要在请求体中指定索引信息):http://ip:port/index

(2).创建索引时,指定索引文档存储的属性信息:http://ip/port/index/type/_mappings

4.DELETE请求

(1).删除索引 (需要在请求体中指定索引信息):http://ip:port/index

(2).删除指定文档信息:http://ip/port/index/type/doc_id

es java es Java框架_es java_02

五、Java连接ES
1.创建Maven工程
2.导入依赖:
(1).elasticsearch
(2).elasticsearch 高级API
(3).junit
(4).lombok
<dependencies>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.5.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.22</version>
        </dependency>
 </dependencies>
3.创建测试类,连接es
public class ESClient {
    public static RestHighLevelClient getClient(){
        //创建HttpHost对象
        HttpHost host = new HttpHost("192.168.99.100",9200);
        //创建 RestClientBuilder
        RestClientBuilder builder = RestClient.builder(host);
        //创建 RestHighLevelClient
        RestHighLevelClient client = new RestHighLevelClient(builder);
        return client;
    }
}

六、Java操作ES索引

/**
 * @ClassName Demo2
 * @Description Java创建ES索引方式
 * @Author AlexChen
 * @Date 2020/8/23 17:17
 * @Version 5.20
 * @WebSite www.codeboy.top
 **/
public class Demo2 {

    RestHighLevelClient client = ESClient.getClient();

    String index = "person";
    String type = "man";

    @Test
    public void createIndex() throws IOException {
       //1.准备关于索引的settings
        Settings.Builder settings = Settings.builder()
                .put("number_of_shards",3)
                .put("number_of_replicas",1);
      //2.准备关于索引的结构
        XContentBuilder mappings = JsonXContent.contentBuilder()
                .startObject()
                    .startObject("properties")
                        .startObject("name")
                            .field("type","text")
                        .endObject()
                        .startObject("age")
                            .field("type","integer")
                        .endObject()
                        .startObject("birthday")
                            .field("type","date")
                            .field("format","yyyy-MM-dd")
                        .endObject()
                    .endObject()
                .endObject();

        //3.将settings 和 mappings 封装到一个Request对象
        CreateIndexRequest request = new CreateIndexRequest(index)
                .settings(settings)
                .mapping(mappings);

        //4.通过client对象去连接ES并执行创建索引
        CreateIndexResponse resp = client.indices().create(request, RequestOptions.DEFAULT);
        //输入resp
        System.out.println("resp>>>"+resp.toString());
    }
}
public class Demo3 {
    String index = "person";
    RestHighLevelClient client = ESClient.getClient();
    /**
     * 判断ES指定索引是否存在
     */
    @Test
    public void exists() throws IOException {
        //1.准备request 对象
        GetIndexRequest request = new GetIndexRequest();
        request.indices(index);
        //2.通过client操作
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        //3.输出结果
        System.out.println("返回值:"+exists);
    }
    /**
     * 删除ES指定索引
     */
    @Test
    public void delete() throws IOException {
        //1.准备request 对象
        DeleteIndexRequest request = new DeleteIndexRequest();
        request.indices(index);
        //2.通过client操作
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        //3.输出结果
        System.out.println("返回值:"+response.isAcknowledged());
    }
}

七、Java操作文档

/**
 * @ClassName TestDoc
 * @Description Java操作文档
 * @Author AlexChen
 * @Date 2020/8/23 18:30
 * @Version 5.20
 * @WebSite www.codeboy.top
 **/
public class TestDoc {

    String index = "person";
    String type = "man";
    ObjectMapper mapper = new ObjectMapper();
    RestHighLevelClient client = ESClient.getClient();

    /**
     * 创建一个文档
     */
   @Test
   public void createPerson() throws IOException {
       //1.创建一个Json数据
       Person person = new Person(1,"张三",23,new Date());
       String json = mapper.writeValueAsString(person);
       //2.准备一个request对象
       IndexRequest request =  new IndexRequest(index,type,person.getId().toString());
       request.source(json, XContentType.JSON);
        //3.通过client对象执行添加操作
       IndexResponse resp = client.index(request, RequestOptions.DEFAULT);
       //4.输出返回结果
       System.out.println(resp.getResult().toString());
   }

    /**
     * 更新一个文档
     */
    @Test
    public void updateDoc() throws IOException {
        //1.创建一个Map对象,指定需要修改的内容
        Map<String, Object> doc = new HashMap<String, Object>();
        doc.put("name","埃里克森");
        String docId = "1";
        //2.创建request对象,封装数据
        UpdateRequest request = new UpdateRequest(index,type,docId);
        request.doc(doc);
        //3.通过client对象执行
        UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
        //4.输出返回结果
        System.out.println(update.getGetResult().toString());
    }


    /**
     * 删除一个文档
     */
    @Test
    public void deleteDoc() throws IOException {
        //1.封装request对象,封装数据
        DeleteRequest request = new DeleteRequest(index,type,"1");
        //2.通过client对象执行
        DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
        //3.输出返回结果
        System.out.println(response.getResult().toString());
    }

    /**
     * 批量添加文档
     */
    @Test
    public void batchCreateDoc() throws IOException {
        //1.准备多个json数据
        Person p1 = new Person(1,"张三",23,new Date());
        Person p2 = new Person(2,"李四",24,new Date());
        Person p3 = new Person(3,"王五",25,new Date());

        String json1 = mapper.writeValueAsString(p1);
        String json2 = mapper.writeValueAsString(p2);
        String json3 = mapper.writeValueAsString(p3);
        //2.创建request对象,将准备好的数据封装进去

        BulkRequest request = new BulkRequest();
        request.add(new IndexRequest(index,type,p1.getId().toString()).source(json1,XContentType.JSON));
        request.add(new IndexRequest(index,type,p2.getId().toString()).source(json2,XContentType.JSON));
        request.add(new IndexRequest(index,type,p3.getId().toString()).source(json3,XContentType.JSON));
        //3.通过client执行
        BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
        //4.输出返回结果
        System.out.println(bulk.toString());
    }

    /**
     * 批量删除文档
     */
    @Test
    public void batchDeleteDoc() throws IOException {
        //1.封装request对象
        BulkRequest request = new BulkRequest();
        request.add(new DeleteRequest(index,type,"1"));
        request.add(new DeleteRequest(index,type,"2"));
        request.add(new DeleteRequest(index,type,"3"));
        //2.通过client执行
        BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
        //3.输出返回结果
        System.out.println(response);
    }
}