Skip to content

引言

要在项目中集成 Elasticsearch 8.17.3,您需要遵循以下步骤。我们将从项目配置、依赖管理、Elasticsearch客户端配置、实体映射、Repository接口定义、以及基本的CRUD操作等方面进行详细说明。

下载安装

访问 Elasticsearch官方 下载页面。

点击 下载 Elasticsearch

然后点击 Windows 下载 ZIP 文件,将下载的文件解压到您希望安装的目录,例如:

js
E:\elasticsearch-8.17.3

修改配置文件

打开 Elasticsearch 的配置文件

js
E:\elasticsearch-8.17.3\config\elasticsearch.yml

修改以下配置(根据需求调整):

yaml
# 设置集群名称
cluster.name: my-elasticsearch-cluster

# 设置节点名称
node.name: node-1

# 绑定到本地IP
network.host: 127.0.0.1

# 设置HTTP端口(默认9200)
http.port: 9200

# 设置集群初始主节点
cluster.initial_master_nodes: ["node-1"]

启用安全功能

Elasticsearch 8.x 默认启用了安全功能(如 HTTPS 和认证),如果您不需要安全功能,可以在 elasticsearch.yml 中禁用:

yaml
xpack.security.enabled: false

启动引擎服务

  • 打开命令提示符(CMD)或 PowerShell

  • 导航到 Elasticsearchbin 目录:

js
cd E:\elasticsearch-8.17.3\bin

  • 运行以下命令启动 Elasticsearch 服务:
js
 .\elasticsearch.bat
  • 如果一切正常,您将看到类似以下的输出:
js
[2023-10-01T12:00:00,000][INFO ][o.e.n.Node               ] [node-1] version[8.17.3], pid[12345], build[default/zip/abcdef1234567890/2023-09-01T12:34:56.789Z], OS[Windows 10/10.0/amd64], JVM[Oracle Corporation/17.0.1/17.0.1+12-LTS-39]
[2023-10-01T12:00:00,000][INFO ][o.e.n.Node               ] [node-1] initialized
[2023-10-01T12:00:00,000][INFO ][o.e.n.Node               ] [node-1] starting ...
[2023-10-01T12:00:00,000][INFO ][o.e.t.TransportService   ] [node-1] publish_address {127.0.0.1:9300}, bound_addresses {127.0.0.1:9300}
[2023-10-01T12:00:00,000][INFO ][o.e.h.AbstractHttpServerTransport] [node-1] publish_address {127.0.0.1:9200}, bound_addresses {127.0.0.1:9200}
[2023-10-01T12:00:00,000][INFO ][o.e.n.Node               ] [node-1] started
  • 打开浏览器,访问以下地址以验证 Elasticsearch 是否正常运行:
js
http://localhost:9200

如果看到类似以下的 JSON 响应,说明 Elasticsearch 已成功启动:

json
{
  "name" : "node-1",
  "cluster_name" : "my-elasticsearch-cluster",
  "cluster_uuid" : "abcdef1234567890",
  "version" : {
    "number" : "8.17.3",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "abcdef1234567890",
    "build_date" : "2023-09-01T12:34:56.789Z",
    "build_snapshot" : false,
    "lucene_version" : "9.7.0",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

添加依赖

pom.xml 中添加阿里云 ElasticSearchSDK 依赖:

js
<!-- ES搜索引擎,要和es版本一致 -->
<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
</dependency>

xiaomayi-common/xiaomayi-elasticsearch 模块中已经引入此依赖,在实际使用时直接引入以下依赖即可:

js
<!-- ElasticSearch 搜索引擎 -->
<dependency>
    <groupId>com.xiaomayi</groupId>
    <artifactId>xiaomayi-elasticsearch</artifactId>
</dependency>

添加服务配置

application-elastic.yml 配置文件中设置Elasticsearch的连接信息。

js
# ES检索服务
elasticsearch:
  # ES服务IP
  host: 127.0.0.1
  # ES服务端口
  port: 9200
  # 登录账号
  username: elastic
  # 登录密码
  password: 123456
  # 访问地址
  uris: localhost:9200

温馨提示

使用时根据实际情况设置 elasticsearch 配置参数 服务IP服务端口登录账号连接地址 等。

创建配置文件

创建 ElasticSearchConfig 参数解析文件,用于服务 YML 配置文件参数:

js
package com.xiaomayi.elasticsearch.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * <p>
 * ES搜索配置类
 * </p>
 *
 * @author 小蚂蚁云团队
 * @since 2024-05-31
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticSearchConfig {

    /**
     * 服务器主机
     */
    private String host;

    /**
     * 服务端口
     */
    private String port;

    /**
     * 登录账号
     */
    private String username;

    /**
     * 登录密码
     */
    private String password;

    /**
     * URI地址,多个逗号分割
     */
    private String uris;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getPort() {
        return port;
    }

    public void setPort(String port) {
        this.port = port;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUris() {
        return uris;
    }

    public void setUris(String uris) {
        this.uris = uris;
    }
}

初始化客户端

我们需要手动配置 ElasticsearchRestHighLevelClient,因为默认的客户端可能不兼容 Elasticsearch 8.x

js
package com.xiaomayi.elasticsearch.config;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

/**
 * <p>
 * ES搜索客户端配置
 * </p>
 *
 * @author 小蚂蚁云团队
 * @since 2024-05-31
 */
@Configuration
public class ElasticSearchClientConfig {

    @Autowired
    private ElasticSearchConfig elasticSearchConfig;

    /**
     * 注册ES对象
     *
     * @return 返回结果
     */
    @Bean
    public ElasticsearchClient client() {
        HttpHost[] httpHosts = toHttpHost();
        // 设置账号密码
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(
                AuthScope.ANY, new UsernamePasswordCredentials(elasticSearchConfig.getUsername(), elasticSearchConfig.getPassword()));

        RestClientBuilder builder = RestClient.builder(httpHosts);
        builder.setRequestConfigCallback(
                new RestClientBuilder.RequestConfigCallback() {
                    @Override
                    public RequestConfig.Builder customizeRequestConfig(
                            RequestConfig.Builder requestConfigBuilder) {
                        return requestConfigBuilder.setSocketTimeout(60000).setConnectTimeout(5000);
                    }
                });
        builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
            @Override
            public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            }
        });
        RestClient restClient = builder.build();
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        return new ElasticsearchClient(transport);
    }

    /**
     * 服务主机处理
     *
     * @return 返回结果
     */
    private HttpHost[] toHttpHost() {
        if (!StringUtils.hasLength(elasticSearchConfig.getUris())) {
            throw new RuntimeException("invalid elasticsearch configuration. elasticsearch.hosts不能为空!");
        }
        // 多个IP逗号隔开
        String[] hostArray = elasticSearchConfig.getUris().split(",");
        HttpHost[] httpHosts = new HttpHost[hostArray.length];
        HttpHost httpHost;
        for (int i = 0; i < hostArray.length; i++) {
            String[] strings = hostArray[i].split(":");
            httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]));
            httpHosts[i] = httpHost;
        }
        return httpHosts;
    }

}

创建工具文件

xiaomayi-common/xiaomayi-elasticsearch 模块中创建了操作工具类 ElasticClientUtils 文件,内容如下:

js
package com.xiaomayi.elasticsearch.utils;


import cn.hutool.extra.spring.SpringUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse;
import co.elastic.clients.elasticsearch.indices.GetIndexResponse;
import co.elastic.clients.transport.endpoints.BooleanResponse;
import com.alibaba.fastjson2.JSON;
import com.xiaomayi.core.utils.StringUtils;
import com.xiaomayi.elasticsearch.dto.ESQueryDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * ES搜索工具类
 * </p>
 *
 * @author 小蚂蚁云团队
 * @since 2024-05-31
 */
@Slf4j
@Component
public class ElasticClientUtils<T> {

    ElasticsearchClient client = SpringUtil.getBean(ElasticsearchClient.class);

    /**
     * 创建ES索引
     *
     * @param indexName 索引名称
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public boolean createIndex(String indexName) throws IOException {
        try {
            // 判断索引是否已存在
            if (indexExists(indexName)) {
                // 存在直接返回true
                return true;
            }
            CreateIndexResponse createIndexResponse = client
                    .indices()
                    .create(c -> c.index(indexName));
            // 返回结果
            return createIndexResponse.acknowledged();
        } catch (IOException e) {
            log.error("向es中创建索引【{}】出错,错误信息为:{}", indexName, e.getMessage());
        }
        return false;
    }

    /**
     * 判断索引是否存在
     *
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public boolean indexExists(String indexName) throws IOException {
        try {
            // 查询索引是否存在
            BooleanResponse exists = client.indices().exists(e -> e.index(indexName));
            // 返回结果
            return exists.value();
        } catch (IOException e) {
            log.error("向es中检测索引【{}】出错,错误信息为:{}", indexName, e.getMessage());
            throw new RuntimeException("向es中检测索引【" + indexName + "】出错");
        }
    }

    /**
     * 查询索引
     *
     * @param indexName 索引名称
     * @throws IOException 异常处理
     */
    public void queryIndex(String indexName) throws IOException {
        try {
            GetIndexResponse getIndexResponse = client.indices().get(c -> c.index(indexName));
            System.out.println(getIndexResponse);
        } catch (IOException e) {
            log.error("向es中添加document出错:{}", e.getMessage());
        }
    }

    /**
     * 删除索引
     *
     * @param indexName 索引名称
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public boolean deleteIndex(String indexName) throws IOException {
        try {
            DeleteIndexResponse deleteIndexResponse = client.indices().delete(c -> c.index(indexName));
            return deleteIndexResponse.acknowledged();
        } catch (IOException e) {
            log.error("向es中删除索引【{}】出错,错误信息为:{}", indexName, e.getMessage());
        }
        return false;
    }

    /**
     * 添加文档
     *
     * @param indexName ES索引
     * @param docId     文档ID
     * @param document  文档对象
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public IndexResponse addDocument(String indexName, String docId, T document) throws IOException {
        try {
            // 判断索引是否存在
            if (!this.indexExists(indexName)) {
                // 不存在索引则创建
                this.createIndex(indexName);
            }
            IndexResponse indexResponse = client.index(i -> i
                    .index(indexName)
                    // 设置文档ID,可以传null
                    .id(docId)
                    // 传入对象
                    .document(document));
            return indexResponse;
        } catch (IOException e) {
            log.error("向es中添加document出错:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 批量插入文档
     *
     * @param indexName         ES索引
     * @param bulkOperationList 对象列表
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public BulkResponse bulkAddDocument(String indexName, List<BulkOperation> bulkOperationList) throws IOException {
        BulkResponse bulkResponse = client.bulk(b -> b
                .index(indexName)
                .operations(bulkOperationList));
        return bulkResponse;
    }

    /**
     * 批量添加
     *
     * @param dataList  添加的数量集合
     * @param indexName indexName
     */
    public void batchAddDocuments(List<T> dataList, String indexName) throws IOException {
        try {
            // 判断索引是否存在
            if (!this.indexExists(indexName)) {
                // 不存在索引则创建
                this.createIndex(indexName);
            }
            // 实例化批量请求
            BulkRequest.Builder builder = new BulkRequest.Builder();
            // 遍历数据源并加入请求对象
            dataList.forEach(data -> builder.operations(op -> op
                            .index(idx -> idx
                                            .index(indexName)
                                            // 如果不需要指定 id,可以省略 id 字段
//                            .id(null)
                                            .document(data)
                            ))
            );
            // 批量添加文档
            BulkResponse result = client.bulk(builder.build());
            if (result.errors()) {
                log.error("Bulk had errors");
                for (BulkResponseItem item : result.items()) {
                    if (item.error() != null) {
                        log.error(item.error().reason());
                    }
                }
            }
        } catch (IOException e) {
            log.error("向es中添加document出错:{}", e.getMessage());
        }
    }

    /**
     * 更新文档
     *
     * @param indexName ES索引
     * @param docId     文档ID
     * @param document  文档对象
     * @param clazz     文档类
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public UpdateResponse updateDocument(String indexName, String docId, T document, Class<T> clazz) throws IOException {
        try {
            UpdateResponse<T> updateResponse = client.update(u -> u
                    .index(indexName)
                    .id(docId)
                    .doc(document), clazz);
            return updateResponse;
        } catch (IOException e) {
            log.error("向es中更新document出错:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 判断文档是否存在
     *
     * @param indexName ES索引
     * @param docId     文档ID
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public BooleanResponse existDocument(String indexName, String docId) throws IOException {
        try {
            BooleanResponse indexResponse = client.exists(e -> e
                    .index(indexName)
                    .id(docId));
            return indexResponse;
        } catch (IOException e) {
            log.error("向es中查询是否存在document出错:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 查询文档
     *
     * @param indexName ES索引
     * @param docId     文档ID
     * @param classz    文档对象
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public GetResponse getDocument(String indexName, String docId, Class<T> classz) throws IOException {
        try {
            GetResponse<T> getResponse = client.get(g -> g
                    .index(indexName)
                    .id(docId), classz);
            return getResponse;
        } catch (IOException e) {
            log.error("向es中查询document出错:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 删除文档
     *
     * @param indexName ES索引
     * @param docId     文档ID
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public DeleteResponse deleteDocument(String indexName, String docId) throws IOException {
        try {
            DeleteResponse deleteResponse = client.delete(d -> d
                    .index(indexName)
                    .id(docId)
            );
            return deleteResponse;
        } catch (IOException e) {
            log.error("向es中删除document出错:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 批量删除文档
     *
     * @param indexName 索引名称
     * @param documentIds 要删除的文档 ID 列表
     * @return 是否全部删除成功
     * @throws IOException 如果删除操作失败
     */
    public boolean bulkDeleteDocuments(String indexName, List<String> documentIds) throws IOException {
        // 构建批量删除请求
        BulkRequest.Builder builder = new BulkRequest.Builder();
        for (String docId : documentIds) {
            builder.operations(op -> op
                    .delete(d -> d
                            .index(indexName)
                            .id(docId)
                    )
            );
        }

        // 执行批量删除
        BulkResponse response = client.bulk(builder.build());

        // 检查是否有错误
        if (response.errors()) {
            for (BulkResponseItem item : response.items()) {
                if (item.error() != null) {
                    System.err.println("Failed to delete document " + item.id() + ": " + item.error().reason());
                }
            }
            return false;
        } else {
            System.out.println("Bulk delete completed successfully!");
            return true;
        }
    }

    /**
     * 根据索引名称和字段查询文档数据
     *
     * @param indexName  索引名称
     * @param filedValue 查询字段值
     * @param filedName  查询字段名称
     */
    public List<T> getDocumentPageList(String indexName, String filedName, String filedValue, Class<T> classz) {
        try {
            SearchResponse<T> searchResponse = client.search(s -> s
                    .index(indexName)
                    .query(q -> q
                            .match(t -> t
                                    .field(filedName)
                                    .query(filedValue)
                            )), classz);
            List<Hit<T>> hitList = searchResponse.hits().hits();
            List<T> dataList = new ArrayList<>();
            for (Hit<T> mapHit : hitList) {
                // 查询结果数据转JSON
                String json = JSON.toJSONString(mapHit.source());
                // 查询结果JSON转对象
                T data = JSON.parseObject(json, classz);
                // 加入列表
                dataList.add(data);
            }
            return dataList;
        } catch (IOException e) {
            log.error("【查询 -> 失败】从es中查询分析后的日志出错,错误信息为:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 查询文档分页数据
     *
     * @param esQueryDTO 查询对象
     * @param classz     实例类名称
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public List<T> getDocumentPage(ESQueryDTO esQueryDTO, Class<T> classz) throws IOException {
        try {
            // 排序规则
            List<SortOptions> sorts = new ArrayList<>();
            if (StringUtils.isNotBlank(esQueryDTO.getOrder())) {
                SortOptions sortOptions = SortOptions.of(s -> s
                        .field(f -> f
                                .field(esQueryDTO.getOrder())
                                .order(SortOrder.valueOf(esQueryDTO.getOrderType())))
                );
                sorts.add(sortOptions);
            }
            // 查询数据源
            SearchResponse<T> search = client.search(s -> s
                            .index(esQueryDTO.getIndexName())
                            .query(q -> q.match(t -> t
                                    .field(esQueryDTO.getField())
                                    .query(esQueryDTO.getWord())
                            ))
                            .sort(sorts)
                            .from(esQueryDTO.getFrom())
                            .size(esQueryDTO.getSize()),
                    classz);
            // 查询结果集
            List<Hit<T>> hitList = search.hits().hits();
            // 实例化查询数据
            List<T> dataList = new ArrayList<>();
            for (Hit<T> mapHit : hitList) {
                // 查询结果数据转JSON
                String json = JSON.toJSONString(mapHit.source());
                // 查询结果JSON转对象
                T data = JSON.parseObject(json, classz);
                // 加入列表
                dataList.add(data);
            }
            return dataList;
        } catch (IOException e) {
            log.error("【查询 -> 失败】从es中查询分页数据出错,错误信息为:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 查询文档数量
     *
     * @param esQueryDTO 查询条件
     * @return 返回结果
     * @throws IOException 异常处理
     */
    public long getDocumentCount(ESQueryDTO esQueryDTO) throws IOException {
        try {
            CountResponse countResponse = client.count(c -> c
                    .index(esQueryDTO.getIndexName())
                    .query(q -> q.term(t -> t
                            .field(esQueryDTO.getField())
                            .value(esQueryDTO.getWord())
                    )));
            // 查询总数
            long count = countResponse.count();
            // 返回结果
            return count;
        } catch (IOException e) {
            log.error("从es中查询数据总数出错,错误信息为:{}", e.getMessage());
        }
        return 0;
    }

}

创建索引

js
/**
 * 创建索引
 *
 * @param indexName 索引名称
 * @return 返回结果
 * @throws IOException 异常处理
 */
@GetMapping("/createIndex/{indexName}")
public R createIndex(@PathVariable String indexName) throws IOException {
    boolean result = elasticClientUtils.createIndex(indexName);
    return R.ok(result);
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": true,
    "ok": true
}

检查索引

js
/**
 * 查询索引
 *
 * @param indexName 索引名称
 * @return 返回结果
 * @throws IOException 异常处理
 */
@GetMapping("/indexExists/{indexName}")
public R indexExists(@PathVariable String indexName) throws IOException {
    boolean result = elasticClientUtils.indexExists(indexName);
    return R.ok(result);
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": true,
    "ok": true
}

检出索引

js
/**
 * 删除索引
 *
 * @param indexName 索引名称
 * @return 返回结果
 * @throws IOException 异常处理
 */
@DeleteMapping("/deleteIndex/{indexName}")
public R deleteIndex(@PathVariable String indexName) throws IOException {
    boolean result = elasticClientUtils.deleteIndex(indexName);
    return R.ok(result);
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": true,
    "ok": true
}

创建文档

js
/**
 * 添加文档
 *
 * @return 返回结果
 * @throws IOException 异常处理
 */
@PostMapping("/addDocument")
public R addDocument() throws IOException {
    // 模拟写入数据
    Level level = new Level();
    level.setName("测试ES文档写入");
    level.setStatus(1);
    level.setSort(1);
    level.setCreateUser("admin");
    level.setCreateTime(LocalDateTime.now());
    level.setUpdateUser("admin");
    level.setUpdateTime(LocalDateTime.now());
    IndexResponse indexResponse = elasticClientUtils.addDocument("xm-example", "XM00001", level);
    return R.ok(indexResponse.result());
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": "Created",
    "ok": true
}

查询文档

js
/**
 * 查询文档内容
 *
 * @return 返回结果
 * @throws IOException 异常处理
 */
@GetMapping("/getDocument")
public R getDocument() throws IOException {
    GetResponse response = elasticClientUtils.getDocument("xm-example", "XM00001", Level.class);
    return R.ok(JSON.toJSONString(response.source()));
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": "{\"createUser\":\"admin\",\"name\":\"测试ES文档写入\",\"sort\":1,\"status\":1,\"updateUser\":\"admin\"}",
    "ok": true
}

检查文档

js
/**
 * 检查文档是否存在
 *
 * @return 返回结果
 * @throws IOException 异常处理
 */
@GetMapping("/existDocument")
public R existDocument() throws IOException {
    BooleanResponse response = elasticClientUtils.existDocument("xm-example", "XM00001");
    return R.ok(response.value());
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": true,
    "ok": true
}

更新文档

js
/**
 * 更新文档
 *
 * @return 返回结果
 * @throws IOException 异常处理
 */
@PostMapping("/updateDocument")
public R updateDocument() throws IOException {
    GetResponse response = elasticClientUtils.getDocument("xm-example", "XM00001", Level.class);
    Level level = (Level) response.source();
    level.setName("文档标题更新");
    level.setStatus(2);
    level.setSort(2);
    UpdateResponse updateResponse = elasticClientUtils.updateDocument("xm-example", "XM00001", level, Level.class);
    return R.ok(updateResponse.result());
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": "Updated",
    "ok": true
}

删除文档

js
/**
 * 删除文档
 *
 * @return 返回结果
 * @throws IOException 异常处理
 */
@DeleteMapping("/deleteDocument")
public R deleteDocument() throws IOException {
    DeleteResponse deleteResponse = elasticClientUtils.deleteDocument("xm-example", "XM00001");
    return R.ok(deleteResponse.result());
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": "Deleted",
    "ok": true
}

批量创建文档

js
/**
 * 批量写入文档
 *
 * @return 返回结果
 * @throws IOException 异常处理
 */
@PostMapping("/batchAddDocument")
public R batchAddDocument() throws IOException {
    List<Level> levelList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        // 模拟写入数据
        Level level = new Level();
        level.setName("文档" + i);
        level.setStatus(1);
        level.setSort(0);
        level.setCreateUser("admin");
        level.setUpdateUser("admin");
        // 加入列表
        levelList.add(level);
    }
    elasticClientUtils.batchAddDocuments(levelList, "xm-example");
    return R.ok();
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": null,
    "ok": true
}

批量删除文档

js
/**
 * 批量删除文档
 *
 * @return 返回结果
 * @throws IOException 异常处理
 */
@DeleteMapping("/bulkDeleteDocuments")
public R bulkDeleteDocuments() throws IOException {
    List<String> documentIds = new ArrayList<>();
    documentIds.add("XM00001");
    boolean result = elasticClientUtils.bulkDeleteDocuments("xm-example", documentIds);
    return R.ok(result);
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": true,
    "ok": true
}

文档分页查询

js
/**
 * 获取分页数据
 *
 * @return 返回结果
 * @throws IOException 异常处理
 */
@GetMapping("/getDocumentPage")
public R getDocumentPage() throws IOException {
    ESQueryDTO esQueryDTO = new ESQueryDTO();
    esQueryDTO.setIndexName("xm-example");
    esQueryDTO.setField("name");
    esQueryDTO.setWord("文档");
    esQueryDTO.setIndex(0);
    esQueryDTO.setSize(10);
    esQueryDTO.setOrder("sort");
    List<Level> levelList = elasticClientUtils.getDocumentPage(esQueryDTO, Level.class);
    return R.ok(levelList);
}

输出结果:

js
{
    "code": 0,
    "msg": "操作成功",
    "data": [
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档0",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档1",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档2",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档3",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档4",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档5",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档6",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档7",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档8",
            "status": 1,
            "sort": 0
        },
        {
            "createUser": "admin",
            "createTime": null,
            "updateUser": "admin",
            "updateTime": null,
            "delFlag": null,
            "tenantId": null,
            "id": null,
            "name": "文档9",
            "status": 1,
            "sort": 0
        }
    ],
    "ok": true
}

总结

通过以上步骤,您已经成功在项目中集成了 Elasticsearch 8.17.3,并实现了基本的 CRUD 操作。您可以根据实际需求进一步扩展和优化这个方案。

注意事项

  • 版本兼容性: 确保Spring Boot、Spring Data Elasticsearch和Elasticsearch客户端的版本兼容。
  • 安全性: 在生产环境中,确保Elasticsearch的访问是安全的,使用HTTPS和认证机制。
  • 性能优化: 根据实际需求调整Elasticsearch的配置,如分片、副本等。

小蚂蚁云团队 · 提供技术支持

小蚂蚁云 新品首发
新品首发,限时特惠,抢购从速! 全场95折
赋能开发者,助理企业发展,提供全方位数据中台解决方案。
获取官方授权