spring boot配置es

Elasticsearch 简介

Elasticsearch(简称 ES)是一个开源的分布式搜索和分析引擎,基于 Apache Lucene 构建,专为处理大规模数据设计。它提供近实时的全文搜索、结构化搜索、分析及数据可视化能力,广泛应用于日志分析、监控系统、企业搜索等场景。

核心特性

分布式架构

Elasticsearch 采用分布式设计,数据自动分片(Sharding)并支持副本(Replica),确保高可用性和横向扩展能力。节点加入或退出集群时,系统自动重新分配数据。

近实时搜索

数据写入后通常在 1 秒内可被检索,适用于需要快速响应的场景,如日志分析或实时监控。

全文搜索

支持复杂的全文检索功能,包括模糊匹配、同义词处理、分词(支持多语言分词器)和高亮显示。

RESTful API

通过 HTTP 接口实现交互,支持 JSON 格式的请求和响应,便于集成到各类应用中。示例:

json 复制代码
GET /_search
{
  "query": { "match": { "message": "error" } }
}

多数据类型支持

  • 结构化数据:如数字、日期、经纬度。
  • 非结构化数据:如文本、JSON 文档。
  • 地理空间数据:支持地理位置查询和聚合。

聚合分析

提供丰富的聚合功能(如平均值、百分位数、地理距离聚合),适用于数据分析和报表生成。

典型应用场景

  • 日志管理与分析:与 Logstash、Kibana 组成 ELK 技术栈,用于集中式日志收集和分析。
  • 电商搜索:支持商品的多条件筛选、排序和推荐。
  • 企业搜索:整合内部文档、数据库等资源,提供统一搜索入口。
  • 安全分析:通过异常检测和模式识别,辅助威胁狩猎(Threat Hunting)。

基本概念

  • 索引(Index):类似数据库中的表,存储相关文档。
  • 文档(Document):索引中的基本数据单元,以 JSON 格式存储。
  • 分片(Shard):索引的子分区,支持水平扩展。
  • 节点(Node):集群中的单个服务器实例,承担数据存储或协调角色。

性能优化建议

  • 根据数据量合理设置分片数,避免过多分片导致开销。
  • 使用批量 API(Bulk API)提升写入效率。
  • 通过 _source 字段控制返回内容,减少网络传输。

Elasticsearch 的灵活性和扩展性使其成为大数据搜索和分析领域的核心工具之一。

添加依赖

js 复制代码
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

配置信息

js 复制代码
  elasticsearch:
    uris: http://xxxxxxx:9200
    username: ${ELASTICSEARCH_USERNAME:elasticsearch}
    password: ${ELASTICSEARCH_PASSWORD:123456}
    connection-timeout: 1s
    socket-timeout: 30s

ElasticsearchConfig配置类

js 复制代码
@Configuration
@EnableElasticsearchRepositories(basePackages = "org.example.repository")
public class ElasticsearchConfig {

    @Value("${spring.elasticsearch.uris}")
    private String elasticsearchUri;

    @Value("${spring.elasticsearch.connection-timeout:1s}")
    private String connectionTimeout;

    @Value("${spring.elasticsearch.socket-timeout:30s}")
    private String socketTimeout;

    /**
     * 创建并配置ElasticsearchClient Bean
     * 
     * @return 配置好的ElasticsearchClient实例
     */
    @Bean
    public ElasticsearchClient elasticsearchClient() {
        // 解析URI获取主机和端口
        String[] uriParts = elasticsearchUri.replace("http://", "").split(":");
        String hostname = uriParts[0];
        int port = Integer.parseInt(uriParts[1]);

        RestClient restClient = RestClient.builder(new HttpHost(hostname, port, "http"))
                .setRequestConfigCallback(builder -> builder
                        .setConnectTimeout(parseTimeValue(connectionTimeout))
                        .setSocketTimeout(parseTimeValue(socketTimeout))
                )
                .build();

        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        return new ElasticsearchClient(transport);
    }

    /**
     * 解析时间值字符串为毫秒数
     * 
     * @param timeValue 时间值字符串,支持秒(s)和毫秒(ms)单位
     * @return 对应的毫秒数
     */
    private int parseTimeValue(String timeValue) {
        if (timeValue.endsWith("s")) {
            return Integer.parseInt(timeValue.replace("s", "")) * 1000;
        } else if (timeValue.endsWith("ms")) {
            return Integer.parseInt(timeValue.replace("ms", ""));
        }
        return 30000; // 默认30秒
    }
}

原生,创建es索引、查询创建的索引、删除索引

js 复制代码
@SpringBootTest
public class TestSkuIndexManage {

    @Autowired
    private ElasticsearchConfig elasticsearchConfig;
    /**
     * 创建es索引
     */
    @Test
    public void test() throws Exception {

        CreateIndexRequest request = CreateIndexRequest.of(c->c
                .index("user"));

        CreateIndexResponse response = elasticsearchConfig.elasticsearchClient()
                .indices()
                .create(request);

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

    }

    /**
     * 检查索引是否存在
     */
    @Test
    public void test2() throws Exception {

        // 检查索引是否存在
        boolean exists = elasticsearchConfig.elasticsearchClient()
                .indices()
                .exists(e -> e.index("user"))
                .value();

        System.out.println("索引 'user' 是否存在: " + exists);
    }

}


	@Test
    public void test3() throws Exception {

        // 删除索引
        boolean deleted = elasticsearchConfig.elasticsearchClient()
                .indices()
                .delete(d -> d.index("user"))
                .acknowledged();

        System.out.println("索引 'user' 是否被删除: " + deleted);
    }

使用 Repository 查询方法

js 复制代码
@Repository
public interface DiscussPostRepository extends ElasticsearchRepository<ClassStudentDTO, String> {

    // 通过ID查询
    Optional<ClassStudentDTO> findById(String id);

    // 通过用户名查询
    List<ClassStudentDTO> findByUsername(String username);

    // 通过工号查询
    List<ClassStudentDTO> findByWorkNumber(String workNumber);

    // 通过状态查询
    List<ClassStudentDTO> findByStatus(Integer status);

    // 通过用户名分页查询
    Page<ClassStudentDTO> findByUsername(String username, Pageable pageable);

    // 根据ID删除
    void deleteById(String id);

    // 根据实体删除
    void delete(ClassStudentDTO entity);

    // 删除所有数据
    void deleteAll();

    // 根据用户名删除
    List<ClassStudentDTO> deleteByUsername(String username);

}

插入数据,查询数据,分页,删除

js 复制代码
@SpringBootTest
public class Test_Doc_Insert {


    @Autowired
    private DiscussPostRepository discussPostRepository;

    /**
     * 测试插入数据
     */
    @Test
    public void test1() throws Exception {

        ClassStudentDTO classStudentDTO = new ClassStudentDTO();
        classStudentDTO.setId(UuidUtils.generate());
        classStudentDTO.setUserId("8snkpxocINqkFeGQ6fxnhAbyvErNASYkQMAd");
        classStudentDTO.setUsername("胡桃");
        classStudentDTO.setWorkNumber("2079943039");
        classStudentDTO.setJoinTime(new Date());
        classStudentDTO.setStatus(1);
        classStudentDTO.setIdentity("学生");


        ClassStudentDTO classStudentDTO1 = discussPostRepository.save(classStudentDTO);
        System.out.println(classStudentDTO1);
    }


    /**
     * 测试查询数据
     */
    @Test
    public void test2() throws Exception {
        List<ClassStudentDTO> list = discussPostRepository.findByUsername("胡桃");
        System.out.println(list);
    }

	/**
     * 测试工号查询数据
     */
    @Test
    public void test3() throws Exception {
        List<ClassStudentDTO> list = discussPostRepository.findByWorkNumber("2079943039");
        System.out.println(list);
    }

	/**
     * 测试名称查询数据,分页
     */
    @Test
    public void test4() throws Exception {
        Pageable pageable = PageRequest.of(0,10);
        Page<ClassStudentDTO> pageResult = discussPostRepository.findByUsername("胡桃", pageable);

        System.out.println("总记录数: " + pageResult.getTotalElements());
        System.out.println("总页数: " + pageResult.getTotalPages());
        System.out.println("当前页数据: " + pageResult.getContent());
        System.out.println("当前页码: " + pageResult.getNumber());
        System.out.println("每页大小: " + pageResult.getSize());
    }
	
	/**
 	* 根据ID删除数据
 	*/
	@Test
	public void testDeleteById() throws Exception {
    	// 假设已知要删除的文档ID
    	String idToDelete = "your-document-id";
    	discussPostRepository.deleteById(idToDelete);
    	System.out.println("已删除ID为 " + idToDelete + " 的文档");
	}

	/**
	 * 根据实体删除数据
	 */
	@Test
	public void testDeleteByEntity() throws Exception {
	    // 先查询出要删除的实体
	    List<ClassStudentDTO> list = discussPostRepository.findByUsername("胡桃");
	    if (!list.isEmpty()) {
	        ClassStudentDTO entityToDelete = list.get(0);
	        discussPostRepository.delete(entityToDelete);
	        System.out.println("已删除实体: " + entityToDelete);
	    }
	}
	
	/**
	 * 删除所有数据
	 */
	@Test
	public void testDeleteAll() throws Exception {
	    discussPostRepository.deleteAll();
	    System.out.println("已删除所有数据");
	}
	
	/**
	 * 根据条件删除数据
	 */
	@Test
	public void testDeleteByUsername() throws Exception {
	    // 需要在Repository中定义findByUsername然后遍历删除
	    List<ClassStudentDTO> list = discussPostRepository.findByUsername("胡桃");
	    discussPostRepository.deleteAll(list);
	    System.out.println("已删除用户名为'胡桃'的所有数据,共" + list.size() + "条");
	}
}

kibana展示

js 复制代码
{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "user",
        "_id": "92rZPN54meTZUfCPIqEswa8dukRWHK9fKMCe",
        "_score": 1,
        "_source": {
          "_class": "org.example.baens.ClassStudentDTO",
          "id": "92rZPN54meTZUfCPIqEswa8dukRWHK9fKMCe",
          "userId": "3wZ5k5WeVRdWzSD8YADdTAS6i3Xyniyn",
          "username": "叶子飞",
          "workNumber": "2079943027",
          "joinTime": "2025-08-14T06:56:10.662Z",
          "status": 1,
          "identity": "教师"
        }
      },
      {
        "_index": "user",
        "_id": "iyoF4chHkH7GloIl8Y4dhQrykCDCNAalOOUw",
        "_score": 1,
        "_source": {
          "_class": "org.example.baens.ClassStudentDTO",
          "id": "iyoF4chHkH7GloIl8Y4dhQrykCDCNAalOOUw",
          "userId": "8snkpxocINqkFeGQ6fxnhAbyvErNASYkQMAd",
          "username": "胡桃",
          "workNumber": "2079943039",
          "joinTime": "2025-08-14T07:00:40.866Z",
          "status": 1,
          "identity": "学生"
        }
      }
    ]
  }
}
相关推荐
Q_Q196328847525 分钟前
python基于Hadoop的超市数据分析系统
开发语言·hadoop·spring boot·python·django·flask·node.js
小乌龟不会飞36 分钟前
【SpringBoot】统一功能处理
java·spring boot·后端
刘小吉40 分钟前
java net 配置局域网受信任的https
后端
考虑考虑1 小时前
JPA中的EntityGraph
spring boot·后端·spring
coolflyr_reg1 小时前
禅道集成Firebase PHP-JWT
后端
似水流年流不尽思念1 小时前
常见的排序算法有哪些?它们的平均时间复杂度是多少?
后端·算法
用户84913717547161 小时前
Access Token + Refresh Token 全解析:前后端分离架构的认证与安全方案
vue.js·spring boot·架构
孟永峰_Java2 小时前
MySQL 组合IN查询:你的索引为什么罢工了?
后端
ruokkk2 小时前
一个困扰我多年的Session超时Bug,被我的新AI搭档半天搞定了
javascript·后端·架构
楽码2 小时前
端到端应用Hmac加密
服务器·后端·算法