Elasticsearch快速部署和入门

乐云一
  • 搜索
  • 搜索
About 2022 wordsAbout 7 min

Elasticsearch快速部署和入门

介绍

本文非常简单粗暴的将Elasticsearch 从0部署到Linux服务后到SpringBoot集成使用Elasticsearch ,适合回顾Elasticsearch和正在接入开发Elasticsearch的人员食用;

先一句话介绍带过Elasticsearch

他是一个集成了Lucene的搜索引擎,其核心功能就是将我们放进去的文档,通过将其设置的关键字分词后,以字典中目录的方式进行倒排序,可搜索我们保存的文档内容

此外,性能高效,分布式,社区活跃,生态完善等因素,使得Elasticsearch 是目前所有搜索引擎框架使用率最高的开源项目

安装与部署

可选择docker容器内部署,或系统应用部署

docker部署

本文以7.12.1版本为例

拉取

docker pull elasticsearch:7.12.1

部署

需要执行两次部署脚本,第一次为拿到elasticsearch的默认文件信息,copy到本地文件中。第二次为将本地文件映射到容器内配置中。

创建容器内私有网络集

docker network create es

第一次运行部署elasticsearch

docker run -d \
  --name elasticsearch \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  -e "discovery.type=single-node" \
  --privileged \
  --network es \
  -p 9200:9200 \
  -p 9300:9300 \
  elasticsearch:7.12.1

将当前运行的elasticsearch配置文件拉取至本地

docker cp elasticsearch:/usr/share/elasticsearch/config {你本地存放elasticsearch文件的地方}
docker cp elasticsearch:/usr/share/elasticsearch/data {你本地存放elasticsearch文件的地方}
docker cp elasticsearch:/usr/share/elasticsearch/logs {你本地存放elasticsearch文件的地方}
docker cp elasticsearch:/usr/share/elasticsearch/plugins {你本地存放elasticsearch文件的地方}

停掉当前运行elasticsearch

docker stop elasticsearch
docker rm elasticsearch

第二次运行部署elasticsearch

docker run -d \
  --name elasticsearch \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  -e "discovery.type=single-node" \   
  -v {你本地存放elasticsearch文件的地方}/data:/usr/share/elasticsearch/data \
  -v {你本地存放elasticsearch文件的地方}/logs:/usr/share/elasticsearch/logs \
  -v {你本地存放elasticsearch文件的地方}/config:/usr/share/elasticsearch/config \
  -v {你本地存放elasticsearch文件的地方}/plugins:/usr/share/elasticsearch/plugins \
  --privileged \
  --network es \
  -p 9200:9200 \
  -p 9300:9300 \
  elasticsearch:7.12.1

安装分词器插件

以IK分词器为例,建议离线安装

先下载分词器:https://release.infinilabs.com/analysis-ik/stable/elasticsearch-analysis-ik-7.12.1.zipopen in new window

https://release.infinilabs.com/analysis-ik/stable/open in new window 中找到自己es版本的下载

将.zip文件放到服务器上,拷贝至docker容器内:

docker cp {文件路径} elasticsearch:/usr/share/elasticsearch

进入到es容器中:

docker exec -it 容器id /bin/sh

安装分词器:

./bin/elasticsearch-plugin install file:elasticsearch-analysis-ik-7.12.1.zip

宿主机部署

由于 elasticsearch 规定死了不能使用root账号启动,因此先创建一个新的账号或使用非root登录

sudo useradd es-user
su es-user

配置

elasticsearchjdk 是强依赖的关系,但是绝大多数的LInux系统中安装的JAVA环境都是Jre。

jdk

elasticsearch 定位jdk环境的顺序为,见/bin/elasticsearch-env文件:

image-20241210161139301

  1. 环境变量 ES_JAVA_HOME
  2. 环境变成 JAVA_HOME
  3. es自带的jdk

此外,elasticsearch 从7.17版本之后就不在支持JDK8,仅支持JDK17之后的高版本jdk了,官网版本对应图:https://www.elastic.co/cn/support/matrix#matrix_jvmopen in new window

jvm

见/config/jvm.options文件

官方仅推荐一个修改jvm配置的方式,除非你明确知道自己在做什么;

所以我们转到config/jvm.options.d/目录下新建文件当作我们的配置,该目录下的文件加载顺序按文件名字典排序:a>b,后文件相同参数可覆盖前文件参数;

文件格式限制为:

#仅在jdk版本为8或超过8的时候起效
8-:-Xmx2g
#仅在jdk版本为8到9的时候起效
8-9:-Xmx2g

需要以 版本号: 进行标注

es配置

见/config/elasticsearch.yml文件

文件配置推荐看:https://blog.csdn.net/gjwgjw1111/article/details/140156042open in new window

一篇很清晰的好文

启动

./bin/elasticsearch

启动过程中,首次部署基本都会出现大大小小的异常,可以根据提示自行在网上找到解决办法;

因为错误提示都太明显,且网络上有很多重复且有效的解决博客,这里不在赘述 :),寻找解决问题的过程真的可以学习很多,非常建议大伙自行操作

Kibana安装

kibana支持Elasticsearch 的文档数据可视化操作,部署也非常简单:

拉取镜像:

docker pull kibana:7.12.1

启动:

docker run -d \
	--name kibana \
	-e ELASTICSEARCH_HOSTS=http://{你部署es的服务器地址}:9200 \
	--network=es \
	-p 5601:5601 \
	kibana:7.12.1\

使用

打开 http://{ip}:5601

image-20241210194641864

image-20241210194656078

依次点击创建想要可视化操作的文档名

image-20241211112011393

image-20241210194741793

选择你想要的可视化界面,完成使用

集成SpringBoot快速入门

引入依赖

版本号和安装的elasticsearch版本对齐,且缺一不可

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

创建客户端

@Component
@ConfigurationProperties(prefix = "spring.elasticsearch")
public class ElasticSearchProperties {

    /**
     * es地址
     */
    private String host;

    /**
     * es端口
     */
    private int port;
}

	@bean
    public RestHighLevelClient restHighLevelClient(ElasticSearchProperties elasticSearchProperties) {
        return new RestHighLevelClient(RestClient.builder(
                new HttpHost(
                        elasticSearchProperties.getHost(),
                        elasticSearchProperties.getPort(),
                        "http"
                )
        ));
    }

操作

本文只简单介绍常用的基本CRUD操作,有需要非常建议查看文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.17/java-rest-high-document-index.htmlopen in new window

配合网络上的各种优质博客食用,因为es已经把api操作封装的特别傻瓜式了 [捂脸.jpg]

假设构建对象 EsConstructBO:

public class EsConstructBO {
    private Object id;
    private JSONObject doc;
}

文档的批量操作

包括批量增加、批量更新、批量删除、批量更新或插入

增加

 private void batchInsert(String indexName, List<EsConstructBO> esConstructs) {
            BulkRequest request = new BulkRequest();
            for (EsConstructBO esConstruct : esConstructs) {
                request.add(new IndexRequest(indexName).id(esConstruct.getId().toString())
                        .opType("create").source(esConstruct.getDoc(), XContentType.JSON));
            }
            restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
    }

更新

 private void batchUpdate(String indexName, List<EsConstructBO> esConstructs) {
            BulkRequest request = new BulkRequest();
            for (EsConstructBO esConstruct : esConstructs) {
                request.add(new UpdateRequest(indexName, esConstruct.getId().toString()).doc(esConstruct.getDoc(), XContentType.JSON));
            }
            restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
    }

删除

 private void batchDelete(String indexName, List<EsConstructBO> esConstructs) {
            BulkRequest request = new BulkRequest();
            for (EsConstructBO esConstruct : esConstructs) {
                request.add(new DeleteRequest(indexName, esConstruct.getId().toString()));
            }
            restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
    }

更新或插入

 private void batchSaveOrUpdate(String indexName, List<EsConstructBO> esConstructs) {
            BulkRequest request = new BulkRequest();
            for (EsConstructBO esConstruct : esConstructs) {
                request.add(new UpdateRequest(indexName, esConstruct.getId().toString()).upsert(XContentType.JSON).doc(esConstruct.getDoc()));
            }
            restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
    }

文档查询

围绕构建SearchSourceBuilder进行查询:

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

比方说需要分页,查询第一页的10条数据则:

        sourceBuilder.size(10);
        sourceBuilder.from(0);

比方说需要根据某些条件进行查询,构建BoolQueryBuilder对象:

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();

某个字段的范围查询,比如时间:

        RangeQueryBuilder rangequerybuilder = QueryBuilders
                  .rangeQuery("createTime");
                  .from(Long.parseLong(String.valueOf(matchMap.get("startTime"))))
                  .to(Long.parseLong(String.valueOf(matchMap.get("endTime"))));
        queryBuilder.must(rangequerybuilder);

需要根据某个字段排序搜索:

		 sourceBuilder.sort("createTime");

根据某个关键字搜索:

		queryBuilder.must(QueryBuilders.termQuery("name","你好"));

根据某几个关键字复合搜索:

		queryBuilder.must(QueryBuilders.multiMatchQuery("关键字",new String[]{"name","age","id"}))

文档中的所有字段作为搜索关键字字段:

		queryBuilder.must(QueryBuilders.queryStringQuery(query.getKeyWord()));

高亮搜索文本中的关键字字符串:

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("高亮的字段名");
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span class='key-text' style='color:red'>");
        highlightBuilder.postTags("</span>");
        sourceBuilder.highlighter(highlightBuilder);

构建之后,搜索实际操作:

		//indexName为数组,填多个时说明本次搜索为多文档复合查询
		SearchRequest searchRequest = new SearchRequest(indexName);
        searchRequest.source(sourceBuilder);
		SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

处理响应参:

public class EsSearchResultData {
    private Long total = 0L;
    private List<T> records = new ArrayList<>();
}
   
    public static EsSearchResultData EsSearchResultData<T> convertSearchResult(SearchResponse searchResponse, Class<T> response) {
        SearchHits hits = searchResponse.getHits();
        EsSearchResultData<T> esSearchResultData = new EsSearchResultData<>();
        esSearchResultData.setTotal(hits.getTotalHits().value);
        List<T> result = new ArrayList<>();
        esSearchResultData.setRecords(result);

        for (SearchHit hit : hits.getHits()) {
            //json字符串
            T o = JSONObject.parseObject(hit.getSourceAsString(), response);
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (CollectionUtil.isNotEmpty(highlightFields)) {
                //高亮匹配到的第一个字段
                o.setDisplayText(highlightFields.values().iterator().next().getFragments()[0].string());
            }
            result.add(o);
        }
        return esSearchResultData;
    }
Last update:
Contributors: LeYunone
Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v2.14.7