Elasticsearch是一个全文搜索引擎,专门用于处理大型数据集。根据描述,自然而然使用它来存储和搜索应用程序日志。与Logstash和Kibana一起,它是强大的解决方案Elastic Stack的一部分,我之前的一些文章中已经对此进行了描述。

保留应用程序日志不是Elasticsearch的唯一使用场景。它通常用作应用程序的辅助数据库,是一个主关系数据库。如果您必须对大型数据集执行全文搜索或仅存储应用程序不再修改的许多历史记录,这个方法尤其有用。当然,该方法也有优缺点。当您使用包含相同数据的两个不同数据源时,您必须首先考虑同步。你有几个选择:根据关系数据库供应商,您可以利用二进制或事务日志,其中包含SQL更新的历史记录。这种方法需要一些中间件来读取日志,然后将数据放入Elasticsearch。您始终可以将整个职责移至数据库端(触发器)或Elasticsearch端(JDBC插件)。

无论您如何将数据导入Elasticsearch,都必须考虑另一个问题:数据结构。关系数据库中的数据可能分布在几个表之间。如果您想利用Elasticsearch,您应该将其存储为单一类型。它会强制您保留冗余数据,这会导致更大的磁盘空间使用量。当然,如果Elasticsearch查询比等效的关系数据库中的查询能更快,那么这种影响是可以接受的。

好的,在长时间的介绍之后继续这个例子。 Spring Boot提供了一种通过Spring Data存储库与Elasticsearch进行交互的简便方法。

1 启用Elasticsearch支持

按照Spring Boot的惯例,我们不必在上下文中提供任何bean来启用对Elasticsearch的支持。我们只需要在pom.xml中添加以下依赖项:

  1. <dependency>

  2. <groupId>org.springframework.boot</groupId>

  3. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>

  4. </dependency>

默认情况下,应用程序尝试在localhost上与Elasticsearch连接。如果我们使用另一个目标URL,我们需要在配置设置中覆盖它。这是我们的application.yml文件的片段,它覆盖了默认的集群名称和地址,以及在Docker容器上启动的Elasticsearch的地址:

  1. spring:

  2. data:

  3. elasticsearch:

  4. cluster-name: docker-cluster

  5. cluster-nodes: 192.168.99.100:9300

应用程序可以通过Spring Boot Actuator health端点监测Elasticsearch连接的运行状况。首先,您需要添加以下Maven依赖项:

  1. <dependency>

  2. <groupId>org.springframework.boot</groupId>

  3. <artifactId>spring-boot-starter-actuator</artifactId>

  4. </dependency>

默认情况下启用Healthcheck,并自动配置Elasticsearch检查。但是,这验证是通过Elasticsearch Rest API客户端执行的。在这种情况下,我们需要覆盖属性spring.elasticsearch.rest.uris-负责设置REST客户端使用的地址:

  1. spring:

  2. elasticsearch:

  3. rest:

  4. uris: http://192.168.99.100:9200

2 运行 Elasticsearch

对于我们的测试,我们需要在开发模式下运行单节点Elasticsearch实例。像往常一样,我们将使用Docker容器。这是Docker容器启动并在9200和9300端口上公开的命令。

  1. $ docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:6.6.2

3 构建Spring Data库

要启用Elasticsearch存储库,我们只需要使用@EnableElasticsearchRepositories注释主类或配置类:

  1. @SpringBootApplication

  2. @EnableElasticsearchRepositories

  3. public class SampleApplication { ... }

下一步是创建扩展CrudRepository的存储库接口。它提供了一些基本操作,如save或findById。如果您想要一些额外的find方法,您应该在跟随Spring Data命名规范在接口内定义新方法。

  1. public interface EmployeeRepository extends CrudRepository<Employee, Long> {

  2. List<Employee> findByOrganizationName(String name);

  3. List<Employee> findByName(String name);

  4. }

4 构建文档

我们的实体关系结构平铺为包含相关对象(组织,部门)的单个Employee对象。您可以将此方法与在RDBMS中为相关表组创建视图进行比较。在Spring Data Elasticsearch命名法中,单个对象存储为文档。因此,需要使用@Document注释对象。您还应该为Elasticsearch设置目标索引的名称,类型和ID。可以使用@Field注解配置其他映射。

  1. @Document(indexName = "sample", type = "employee")

  2. public class Employee {

  3. @Id

  4. private Long id;

  5. @Field(type = FieldType.Object)

  6. private Organization organization;

  7. @Field(type = FieldType.Object)

  8. private Department department;

  9. private String name;

  10. private int age;

  11. private String position;

  12. // Getters and Setters ...

  13. }

5 初始化数据

正如在前言中提到的,您可能决定使用Elasticsearch的主要原因是需要处理大数据。因此,最好使用大量文档填充我们的测试Elasticsearch节点。如果您想在一步就插入许多文档,那么您一定要使用Bulk API。bulk API使得在单个API调用中执行许多索引/删除操作成为可能。这可以大大提高索引速度。可以使用Spring Data ElasticsearchTemplate bean执行批量操作。它在Spring Boot上也可以自动配置。 Template提供了bulkIndex方法,该方法将索引查询列表作为输入参数。这是在应用程序启动时插入样本测试数据的bean的实现:

  1. public class SampleDataSet {

  2. private static final Logger LOGGER = LoggerFactory.getLogger(SampleDataSet.class);

  3. private static final String INDEX_NAME = "sample";

  4. private static final String INDEX_TYPE = "employee";

  5. @Autowired

  6. EmployeeRepository repository;

  7. @Autowired

  8. ElasticsearchTemplate template;

  9. @PostConstruct

  10. public void init() {

  11. for (int i = 0; i < 10000; i++) {

  12. bulk(i);

  13. }

  14. }

  15. public void bulk(int ii) {

  16. try {

  17. if (!template.indexExists(INDEX_NAME)) {

  18. template.createIndex(INDEX_NAME);

  19. }

  20. ObjectMapper mapper = new ObjectMapper();

  21. List<IndexQuery> queries = new ArrayList<>();

  22. List<Employee> employees = employees();

  23. for (Employee employee : employees) {

  24. IndexQuery indexQuery = new IndexQuery();

  25. indexQuery.setId(employee.getId().toString());

  26. indexQuery.setSource(mapper.writeValueAsString(employee));

  27. indexQuery.setIndexName(INDEX_NAME);

  28. indexQuery.setType(INDEX_TYPE);

  29. queries.add(indexQuery);

  30. }

  31. if (queries.size() > 0) {

  32. template.bulkIndex(queries);

  33. }

  34. template.refresh(INDEX_NAME);

  35. LOGGER.info("BulkIndex completed: {}", ii);

  36. } catch (Exception e) {

  37. LOGGER.error("Error bulk index", e);

  38. }

  39. }

  40. // sample data set implementation ...

  41. }

如果您不需要在启动时插入数据,则可以通过将属性initial-import由enabled转变为false来禁用该过程。这是SampleDataSet bean的声明:

  1. @Bean

  2. @ConditionalOnProperty("initial-import.enabled")

  3. public SampleDataSet dataSet() {

  4. return new SampleDataSet();

  5. }

6 查看数据和运行查询

假设您已经启动了示例应用程序,负责扩充索引的bean没有被禁用,并且有足够的耐心等待几个小时,直到所有数据都插入到Elasticsearch节点中,现在它包含100M的员工类型文档。显示集群有关的一些信息是值得的。您可以使用Elasticsearch查询来执行此操作,也可以下载一个可用的GUI工具,例如ElasticHQ。碰巧的是,ElasticHQ也可以作为Docker容器使用。您必须执行以下命令才能启动ElasticHQ容器:

  1. $ docker run -d --name elastichq -p 5000:5000 elastichq/elasticsearch-hq

启动ElasticHQ后,Web浏览器通过端口5000访问GUI。它的Web控制台提供有关集群,索引和允许执行查询的基本信息。您只需要输入Elasticsearch节点地址,您将被重定向到带有统计信息的主仪表盘。这是ElasticHQ的主仪表盘。

如您所见,我们有一个名为sample的索引,分为5个分片。这是Spring Data @Document提供的默认值,可以使用分片字段覆盖它。点击后我们可以导航到索引管理面板。您可以对索引执行某些操作例如清除缓存或刷新索引等。您还可以查看所有分片的统计信息。

出于当前的测试目的,我有大约25M(约3GB的空间)Employee类型的文档。我们可以执行一些测试查询。我已经公开了两个用于搜索的端点:按员工姓名GET/employees/{name}和组织名称GET/employees / organization / {organizationName}。结果并不是压倒性的。我认为关系数据库使用相同数量的数据也可以获得相同的结果。

7 测试

好的,我们已经完成了开发并对大型数据集进行了一些手动测试。现在,是时候创建一些在构建时运行的集成测试了。我们可以使用允许在JUnit测试期间自动启动数据库的Docker容器的库 - Testcontainers。有关此库的更多信息,请参阅其站点https://www.testcontainers.org或我以前的一篇文章:使用Testcontainers Framework测试Spring与Vault和Postgres的集成。幸运的是,Testcontainers支持Elasticsearch。要在测试范围内启用它,首先需要在pom.xml中添加以下依赖项:

  1. <dependency>

  2. <groupId>org.testcontainers</groupId>

  3. <artifactId>elasticsearch</artifactId>

  4. <version>1.11.1</version>

  5. <scope>test</scope>

  6. </dependency>

下一步是定义指向Elasticsearch容器的@ClassRule或@Rule bean。它在测试类之前或每个依赖使用的注释之前自动启动。公开的端口号是自动生成的,因此您需要将其设置为spring.data.elasticsearch.cluster-nodes属性的值。这是我们的JUnit集成测试的完整实现:

  1. @RunWith(SpringRunner.class)

  2. @SpringBootTest

  3. @FixMethodOrder(MethodSorters.NAME_ASCENDING)

  4. public class EmployeeRepositoryTest {

  5. @ClassRule

  6. public static ElasticsearchContainer container = new ElasticsearchContainer();

  7. @Autowired

  8. EmployeeRepository repository;

  9. @BeforeClass

  10. public static void before() {

  11. System.setProperty("spring.data.elasticsearch.cluster-nodes", container.getContainerIpAddress() + ":" + container.getMappedPort(9300));

  12. }

  13. @Test

  14. public void testAdd() {

  15. Employee employee = new Employee();

  16. employee.setId(1L);

  17. employee.setName("John Smith");

  18. employee.setAge(33);

  19. employee.setPosition("Developer");

  20. employee.setDepartment(new Department(1L, "TestD"));

  21. employee.setOrganization(new Organization(1L, "TestO", "Test Street No. 1"));

  22. employee = repository.save(employee);

  23. Assert.assertNotNull(employee);

  24. }

  25. @Test

  26. public void testFindAll() {

  27. Iterable<Employee> employees = repository.findAll();

  28. Assert.assertTrue(employees.iterator().hasNext());

  29. }

  30. @Test

  31. public void testFindByOrganization() {

  32. List<Employee> employees = repository.findByOrganizationName("TestO");

  33. Assert.assertTrue(employees.

Spring Boot整合Elasticsearch的更多相关文章

  1. 【spring boot】【elasticsearch】spring boot整合elasticsearch,启动报错Caused by: java.lang.IllegalStateException: availableProcessors is already set to [8], rejecting [8

    spring boot整合elasticsearch, 启动报错: Caused by: java.lang.IllegalStateException: availableProcessors ], ...

  2. Elasticsearch学习(3) spring boot整合Elasticsearch的原生方式

    前面我们已经介绍了spring boot整合Elasticsearch的jpa方式,这种方式虽然简便,但是依旧无法解决我们较为复杂的业务,所以原生的实现方式学习能够解决这些问题,而原生的学习方式也是E ...

  3. Spring Boot 整合 Elasticsearch,实现 function score query 权重分查询

    摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 预见未来最好的方式就是亲手创造未来 – <史蒂夫·乔布斯传> 』 运行环境: ...

  4. spring boot 整合 elasticsearch 5.x

    spring boot与elasticsearch集成有两种方式.一种是直接使用elasticsearch.一种是使用data中间件. 本文只指针使用maven集成elasticsearch 5.x, ...

  5. Spring Boot 整合 elasticsearch

    一.简介 我们的应用经常需要添加检索功能,开源的 ElasticSearch 是目前全文搜索引擎的 首选.他可以快速的存储.搜索和分析海量数据.Spring Boot通过整合Spring Data E ...

  6. Elasticsearch学习(1) Spring boot整合Elasticsearch

    本文的Spring Boot版本为1.5.9,Elasticsearch版本为2.4.4,话不多说,直接上代码. 一.启动Elasticsearch 在官网上下载Elasticsearch后,打开bi ...

  7. Spring Boot整合ElasticSearch和Mysql 附案例源码

    导读 前二天,写了一篇ElasticSearch7.8.1从入门到精通的(点我直达),但是还没有整合到SpringBoot中,下面演示将ElasticSearch和mysql整合到Spring Boo ...

  8. Elasticsearch学习(4) spring boot整合Elasticsearch的聚合操作

    之前已将spring boot原生方式介绍了,接下将结介绍的是Elasticsearch聚合操作.聚合操作一般来说是解决一下复杂的业务,比如mysql中的求和和分组,由于博主踩的坑比较多,所以博客可能 ...

  9. spring boot 整合elasticsearch

    1.导入jar包 <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncodi ...

随机推荐

  1. PHP八大设计模式

    设计模式 单例模式解决的是如何在整个项目中创建唯一对象实例的问题,工厂模式解决的是如何不通过new建立实例对象的方法. 单例模式 $_instance必须声明为静态的私有变量 构造函数和析构函数必须声 ...

  2. js常用JSON数据操作

    JSON字符串: var  str = '{"name": "jack", "age": 13}'; JSON对象: var obj = { ...

  3. Retrofit+MVP框架封装记录篇

    当下最流行的网络请求组合,retrofit2+okhttp+rxjava+mvp 这里是封装记录篇 首先分模块,比如登录 先来说封装后的使用 package com.fragmentapp.login ...

  4. Python 经典面试题汇总之网络篇

    网络篇 1.简述 OSI 七层协议 物理层:定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质. 数据链路层:定义如何传输格式化数据,以及如何访问物理介质. 网络层:定义逻辑网络地址. ...

  5. MongoDB 基础(2019年开篇)

    MongoDB基础知识: 1.什么是MongoDB NoSQL(NoSQL=Not Only SQL),意即"不仅仅是SQL". MongoDB是一个介于关系数据库和非关系数据库之 ...

  6. 好代码是管出来的——.Net Core集成测试与数据驱动测试

    软件的单元测试关注是的软件最小可执行单元是否能够正常执行,但是软件是由一个个最小执行单元组成的集合体,单元与单元之间存在着种种依赖或联系,所以在软件开发时仅仅确保最小单元的正确往往是不够的,为了保证软 ...

  7. mysqlbinlog 工具分析binlog日志

    MySQL的binlog 日志对于生产环境非常有用,任何时间对数据库的修改都会记录在binglog中:当数据发生增删改,创建数据库对象都会记录到binlog中,数据库的复制也是基于binlog进行同步 ...

  8. Oracle函数——日期函数

    Oracle中的时间类型只有date和TIMESTAMP,TIMESTAMP是比date更精确的类型.日期时间函数用于处理时间类型的数据,Oracle以7位数字格式来存放日期数据,包括世纪.年.月.日 ...

  9. 好程序员分享该如何选择background-image和img标签

    好程序员分享该如何选择background-image和img标签,用img标签 如果你希望别人打印页面时候包含这张图片请使用img标签 当这张图片有非常有意义的语义,比如警告图标,请使用img标签及 ...

  10. 利用 keras_proprecessing.image 扩增自己的遥感数据(多波段)

    1.keras 自带的 keras_proprecessing.image 只支持三种模式图片(color_mode in ['grey', 'RGB', 'RGBA'])的随机扩增. 2.遥感数据除 ...