前言

Elasticsearch 是位于 Elastic Stack 核心的分布式搜索和分析引擎。Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。Kibana 使您能够以交互方式探索、可视化和分享对数据的见解,并管理和监控堆栈。Elasticsearch 是索引、搜索和分析魔法发生的地方。
Elasticsearch 为所有类型的数据提供近乎实时的搜索和分析。无论您拥有结构化或非结构化文本、数字数据还是地理空间数据,Elasticsearch 都能以支持快速搜索的方式高效地存储和索引它。您可以超越简单的数据检索和聚合信息来发现数据中的趋势和模式。随着您的数据和查询量的增长,Elasticsearch 的分布式特性使您的部署能够随之无缝增长。


下载

Elastic官方网站:点击前往官方下载网站页面
Elasitc所有版本:本链接还是官网的
Elastic国内站点:点击前往国内站点

官网链接可能会有点慢,需要科学上网
国内站点少东西,mac版本不带jdk,推荐官网链接,下的慢也要等

安装

我选择的是7.17.6的版本进行安装,可以按照自己的需求安装相应的版本
Elastic-Study-1

下载好后解压到任意地方,然后里面的内容应该如下
Elasitc-Study-2

默认配置文件为 /config/elasticsearch.yml
启动文件为 /bin/elasticsearch
配置文件一般用来配置集群相关设置,后续会慢慢解释

启动Elasitc

打开cmd或者console终端控制器,输入 ./elasticsearch 即可完成启动
Elastic-Study-3
在本地浏览器浏览 localhost:9200 可以查看是否启动成功 点击直接前往该地址
启动成功后,应该是如下的显示效果,反之请检查之前的步骤是否有遗落的
Elastic-Study-4


基础操作

下载、安装和启动这些过程都结束后,我们就可以开始进行一些基础操作的测试了
需要用到Postman软件:Postman官网网站
Postman下载页面:Postman Mac版本下载页面

Elastic-Study-5
Elastic-Study-6

通过以上的方式,已经完成了基础的测试
下面通过put一个sell index,并且get进行测试一下
Elastic-Study-7
Elastic-Study-8


Java代码操作

引入依赖

创建一个Maven项目并添加依赖

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>2.17.2</version>
    </dependency>

    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.17.2</version>
    </dependency>

    <dependency>
      <groupId>co.elastic.clients</groupId>
      <artifactId>elasticsearch-java</artifactId>
      <version>7.17.6</version>
    </dependency>

    <dependency>
      <groupId>org.elasticsearch.client</groupId>
      <artifactId>elasticsearch-rest-high-level-client</artifactId>
      <version>7.17.6</version>
    </dependency>

    <dependency>
      <groupId>org.elasticsearch</groupId>
      <artifactId>elasticsearch</artifactId>
      <version>7.17.6</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.1</version>
    </dependency>
  </dependencies>

使用的是阿里云的Maven镜像链接,需要注意依赖版本和elastic版本相对应

依赖使用了RestHighLevelClient,该方式已经是过时方法
可以使用 Elasticsearch Java API Client 对ES进行操作

RestHighLevelClient方式

创建连接

public class ESTest_Client {

    public static void main(String[] args) throws IOException {

        // 创建 ES 客户端
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 关闭 ES 客户端
        esClient.close();
    }
}

创建索引

public class ESTest_Index_Create {

    public static void main(String[] args) throws IOException {
        
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 创建索引
        CreateIndexRequest request = new CreateIndexRequest("user02");
        CreateIndexResponse createIndexResponse =
                esClient.indices().create(request, RequestOptions.DEFAULT);
        // 响应状态
        boolean acknowledged = createIndexResponse.isAcknowledged();
        System.out.println("索引操作" + acknowledged);
        
        esClient.close();

    }
}

查询索引

public class ESTest_Index_Search {

    public static void main(String[] args) throws IOException {
        
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 查询索引
        GetIndexRequest request = new GetIndexRequest("user02");
        GetIndexResponse getIndexResponse = esClient.indices().get(request, RequestOptions.DEFAULT);
        // 响应状态
        System.out.println(getIndexResponse.getAliases());
        System.out.println(getIndexResponse.getMappings());
        System.out.println(getIndexResponse.getSettings());
        
        esClient.close();
    }
}

删除索引

public class ESTest_Index_Delete {

    public static void main(String[] args) throws IOException {
        
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 删除索引
        DeleteIndexRequest request = new DeleteIndexRequest("user02");
        AcknowledgedResponse response = esClient.indices().delete(request, RequestOptions.DEFAULT);
        // 响应状态
        System.out.println(response.isAcknowledged());
        
        esClient.close();
    }
}

文档插入数据

public class ESTest_Doc_Insert {

    public static void main(String[] args) throws IOException {
        
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 插入数据
        IndexRequest request = new IndexRequest();
        request.index("user01").id("1001");

        User user = new User("zhangsan","man",30);
        //向 ES 插入数据,必须将数据转换为JSON格式
        ObjectMapper mapper = new ObjectMapper();
        String userJson = mapper.writeValueAsString(user);
        request.source(userJson, XContentType.JSON);

        IndexResponse response = esClient.index(request, RequestOptions.DEFAULT);

        System.out.println(response.getResult());

        esClient.close();
    }
}

文档批量插入数据

public class ESTest_Doc_Insert_Batch {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 批量插入数据
        BulkRequest request = new BulkRequest();

        request.add(new IndexRequest().index("user01").id("1001").source(XContentType.JSON,"name","zhangsan","age",30,"sex","man"));
        request.add(new IndexRequest().index("user01").id("1002").source(XContentType.JSON,"name","lisi","age",40,"sex","man"));
        request.add(new IndexRequest().index("user01").id("1003").source(XContentType.JSON,"name","wangwu","age",50,"sex","woman"));
        request.add(new IndexRequest().index("user01").id("1004").source(XContentType.JSON,"name","wangwu2","age",20,"sex","woman"));
        request.add(new IndexRequest().index("user01").id("1005").source(XContentType.JSON,"name","wangwu3","age",10,"sex","man"));
        request.add(new IndexRequest().index("user01").id("1006").source(XContentType.JSON,"name","wangwu4","age",60,"sex","woman"));

        BulkResponse bulk = esClient.bulk(request, RequestOptions.DEFAULT);
        System.out.println(bulk.getTook());

        esClient.close();
    }
}

文档删除数据

public class ESTest_Doc_Delete {

    public static void main(String[] args) throws IOException {
        
        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 删除数据
        DeleteRequest request = new DeleteRequest();
        request.index("user01").id("1001");
        DeleteResponse delete = esClient.delete(request, RequestOptions.DEFAULT);

        System.out.println(delete.toString());
        
        esClient.close();
    }
}

文档批量删除数据

public class ESTest_Doc_Delete_Batch {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 批量删除数据
        BulkRequest request = new BulkRequest();

        request.add(new DeleteRequest().index("user01").id("1001"));
        request.add(new DeleteRequest().index("user01").id("1002"));
        request.add(new DeleteRequest().index("user01").id("1003"));

        BulkResponse bulk = esClient.bulk(request, RequestOptions.DEFAULT);

        System.out.println(bulk.getTook());

        esClient.close();
    }
}

文档查询数据

public class ESTest_Doc_Get {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 查询数据
        GetRequest request = new GetRequest();
        request.index("user01").id("1001");
        GetResponse response = esClient.get(request, RequestOptions.DEFAULT);

        System.out.println(response.getSourceAsString());

        esClient.close();
    }
}

文档修改数据

public class ESTest_Doc_Update {

    public static void main(String[] args) throws IOException {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200,"http"))
        );

        // 修改数据
        UpdateRequest request = new UpdateRequest();
        request.index("user01").id("1001");
        request.doc(XContentType.JSON,"sex","woman");

        UpdateResponse response = esClient.update(request,RequestOptions.DEFAULT);

        System.out.println(response.getResult());

        esClient.close();
    }
}

文档更多的查询数据

// 查询数据 所有数据
SearchRequest request = new SearchRequest();
request.indices("user01");

request.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(hits.getTotalHits());
System.out.println(response.getTook());

for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}
// 条件查询
SearchRequest request = new SearchRequest();
request.indices("user01");

request.source(new SearchSourceBuilder().query(QueryBuilders.termQuery("age",30)));

SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(hits.getTotalHits());
System.out.println(response.getTook());

for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}
// 分页查询
SearchRequest request = new SearchRequest();
request.indices("user01");

SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
builder.from(0);
builder.size(2);

request.source(builder);

SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(hits.getTotalHits());
System.out.println(response.getTook());

for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}
// 查询排序
SearchRequest request = new SearchRequest();
request.indices("user01");

SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
builder.sort("age", SortOrder.DESC);

request.source(builder);

SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(hits.getTotalHits());
System.out.println(response.getTook());

for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}
// 过滤查询
SearchRequest request = new SearchRequest();
request.indices("user01");

SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
String[] excludes = {"age"};
String[] includes = {};
builder.fetchSource(includes,excludes);

request.source(builder);

SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(hits.getTotalHits());
System.out.println(response.getTook());

for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}
//     组合查询
SearchRequest request = new SearchRequest();
request.indices("user01");

SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

///        boolQueryBuilder.must(QueryBuilders.matchQuery("age",30));
///        boolQueryBuilder.must(QueryBuilders.matchQuery("sex","man"));
///        boolQueryBuilder.mustNot(QueryBuilders.matchQuery("sex","man"));
boolQueryBuilder.should(QueryBuilders.matchQuery("age",30));
boolQueryBuilder.should(QueryBuilders.matchQuery("age",40));


builder.query(boolQueryBuilder);
request.source(builder);

SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(hits.getTotalHits());
System.out.println(response.getTook());

for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}
/// 范围查询
SearchRequest request = new SearchRequest();
request.indices("user01");

SearchSourceBuilder builder = new SearchSourceBuilder();
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");

rangeQuery.gte(30);
rangeQuery.lt(50);

builder.query(rangeQuery);
request.source(builder);

SearchResponse response = esClient.search(request,RequestOptions.DEFAULT);

SearchHits hits = response.getHits();

System.out.println(hits.getTotalHits());
System.out.println(response.getTook());

for (SearchHit hit : hits) {
    System.out.println(hit.getSourceAsString());
}

Elastic Java API 方式

创建连接

public void create() throws IOException {
        // 创建低级客户端
        RestClient restClient = RestClient.builder(
                new HttpHost("localhost", 9200)
        ).build();
        // 使用Jackson映射器创建传输层
        ElasticsearchTransport transport = new RestClientTransport(
                restClient, new JacksonJsonpMapper()
        );
        // 创建API客户端
        ElasticsearchClient client = new ElasticsearchClient(transport);

        // 关闭ES客户端
        transport.close();
        restClient.close();
}

创建索引

public void create() throws IOException {

    // 创建低级客户端
    RestClient restClient = RestClient.builder(
            new HttpHost("localhost", 9200)
    ).build();
    // 使用Jackson映射器创建传输层
    ElasticsearchTransport transport = new RestClientTransport(
            restClient, new JacksonJsonpMapper()
    );
    // 创建API客户端
    ElasticsearchClient client = new ElasticsearchClient(transport);
    // 创建索引
    CreateIndexResponse createIndexResponse = client.indices().create(c -> c.index("user_test"));
    // 响应状态
    Boolean acknowledged = createIndexResponse.acknowledged();
    System.out.println("索引操作 = " + acknowledged);

    // 关闭ES客户端
    transport.close();
    restClient.close();

}

配置集群

ES 作为一个搜索引擎,我们对它的基本要求就是存储海量数据并且可以在非常短的时间内查询到我们想要的信息。所以第一步我们需要保证的就是 ES 的高可用性。什么是高可用性呢?它通常是指,通过设计减少系统不能提供服务的时间。假设系统一直能够提供服务,我们说系统的可用性是 100%,如果系统在某个时刻宕掉了,比如某个网站在某个时间挂掉了,那么就可以说它临时是不可用的。所以,为了保证 ES 的高可用性,我们就应该尽量减少 ES 的不可用时间。
如果你只有一台主机的话,其实索引的健康状况也是 yellow,因为只有一台主机,没有其他的主机可以放置副本,所以说,这就是一个不健康的状态,因此集群也是十分有必要的。
既然是集群,那么存储空间肯定也是联合起来的,假如一台主机的存储空间是固定的,那么集群相对于单机也有更多的存储空间,可存储的数据量也更大。

所以综上所述,项目中使用 ES 时,一般采用集群模式,而非单机模式。

Elastic-集群-1

按照之前Elastic的下载安装步骤,将Elastic解压,并且复制粘贴成3个文件夹,我分别命名为node-1001、node-1002、node-1003
然后分别更改里面的 /config/elasticsearch.yml 配置文件

node-1001 配置文件

#集群cluster的名称 所有node的cluster名称都要保持一致
cluster.name: my-application

#node节点名字 每一个节点的node名字都要不一样
node.name: node-1001
node.master: true
node.data: true

#链接的地址
network.host: localhost

#对外9201端口连接 对内9301端口连接
http.port: 9201
transport.tcp.port: 9301

#启用http
http.cors.enabled: true
http.cors.allow-origin: "*"

node-1002 配置文件

cluster.name: my-application

node.name: node-1002
node.master: true
node.data: true

network.host: localhost

http.port: 9202
transport.tcp.port: 9302

#其他node均需要添加前面的节点
#通过内部端口连接
discovery.seed_hosts: ["localhost:9301"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5

http.cors.enabled: true
http.cors.allow-origin: "*"

node-1003 配置文件

cluster.name: my-application

node.name: node-1003
node.master: true
node.data: true

network.host: localhost

http.port: 9203
transport.tcp.port: 9303

#和node-1002节点设置一样 但是要找到之前的所有节点
discovery.seed_hosts: ["localhost:9301","localhost:9302"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5

http.cors.enabled: true
http.cors.allow-origin: "*"

Elastic-集群-2

启动3个elastic后,在postman中对 http://127.0.0.1:9201/_cluster/health
发送GET请求,可以得到以上的内容,里面包含了cluster的名字、状态、node节点的数量等等


要知道,人吃饭,不但是肚子的需要,而且是一种精神需要。不知道下一顿在什么地方,人就特别想到吃,而且,饿得快。“他说:”你家道尚好的时候,有这种精神压力吗?恐怕没有什么精神需求吧?有,也只不过是想好上再好,那是馋。馋是你们这些人的特点。 —— 阿城《棋王》
最后修改:2023 年 01 月 09 日
如果觉得我的文章对你有用,请随意赞赏