elasticsearch 客户端工具_在springBoot 中使用Elasticsearch

在springBoot 中使用Elasticsearch

cf4e95e2f246bd5395d1d8f0aaf6a65b.png

Elasticsearch是一个全文本搜索引擎,专门用于处理大型数据集。根据此描述,自然使用它来存储和搜索应用程序日志。与Logstash和Kibana一起,它是称为Elastic Stack的强大解决方案的一部分。

保留应用程序日志并不是Elasticsearch的唯一的一种用法。它通常用作具有主关系数据库的应用程序的辅助数据库。如果您必须对大型数据集执行全文搜索,或者仅存储许多不再由应用程序修改的历史记录,则这种方法特别有用。当然,对于这种方法的优缺点总是存在疑问。 当使用包含相同数据的两个不同数据源时,必须首先考虑同步。您有几种选择。根据关系数据库供应商的不同,您可以利用包含SQL更新历史记录的二进制或事务日志。这种方法需要一些中间件,该中间件先读取日志,然后将数据放入Elasticsearch。您始终可以将全部责任移到数据库端(触发)或Elasticsearch端(JDBC插件)。 无论您如何将数据导入Elasticsearch,都必须考虑另一个问题。数据结构。您可能在关系数据库中的几个表之间分配了数据。如果您想利用Elasticsearch的优势,则应将其存储为单个类型。它迫使您保留冗余数据,从而导致更大的磁盘空间使用。当然,如果查询比关系数据库中的等效查询运行得更快,那么这种效果是可以接受的。好的,在介绍了很长时间之后,让我们继续该示例。Spring Boot提供了一种通过Spring Data存储库与Elasticsearch进行交互的简便方法。

1.启用ELASTICSEARCH支持

按照Spring Boot的习惯,我们不必在上下文中提供任何其他Bean来支持对Elasticsearch的支持。我们只需要包括以下对我们的依赖pom.xml:

    org.springframework.boot    spring-boot-starter-data-elasticsearch

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

spring:  data:    elasticsearch:      cluster-name: docker-cluster      cluster-nodes: 192.168.99.100:9300

应用程序可以通过Spring Boot Actuator health端点公开Elasticsearch连接的健康状态。首先,您需要包括以下Maven依赖项:

    org.springframework.boot    spring-boot-starter-actuator

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

spring:  elasticsearch:    rest:      uris: http://192.168.99.100:9200

2.运行ELASTICSEARCH

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

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

3.建立SPRING数据仓库

要启用Elasticsearch存储库,我们只需要使用以下方法注释main或configuration类

@EnableElasticsearchRepositories:@SpringBootApplication@EnableElasticsearchRepositoriespublic class SampleApplication { ... }

下一步是创建扩展的存储库接口CrudRepository。它提供了一些基本操作,例如save或findById。如果您想要其他一些find方法,则应遵循Spring Data命名约定在接口内定义新方法。

public interface EmployeeRepository extends CrudRepository {     List findByOrganizationName(String name);    List findByName(String name); }

4.实体对象

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

@Document(indexName = "sample", type = "employee")public class Employee {     @Id    private Long id;    @Field(type = FieldType.Object)    private Organization organization;    @Field(type = FieldType.Object)    private Department department;    private String name;    private int age;    private String position;         // Getters and Setters ... }

5.初始化

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

public class SampleDataSet {     private static final Logger LOGGER = LoggerFactory.getLogger(SampleDataSet.class);    private static final String INDEX_NAME = "sample";    private static final String INDEX_TYPE = "employee";     @Autowired    EmployeeRepository repository;    @Autowired    ElasticsearchTemplate template;     @PostConstruct    public void init() {        for (int i = 0; i < 10000; i++) {            bulk(i);        }    }     public void bulk(int ii) {        try {            if (!template.indexExists(INDEX_NAME)) {                template.createIndex(INDEX_NAME);            }            ObjectMapper mapper = new ObjectMapper();            List queries = new ArrayList<>();            List employees = employees();            for (Employee employee : employees) {                IndexQuery indexQuery = new IndexQuery();                indexQuery.setId(employee.getId().toString());                indexQuery.setSource(mapper.writeValueAsString(employee));                indexQuery.setIndexName(INDEX_NAME);                indexQuery.setType(INDEX_TYPE);                queries.add(indexQuery);            }            if (queries.size() > 0) {                template.bulkIndex(queries);            }            template.refresh(INDEX_NAME);            LOGGER.info("BulkIndex completed: {}", ii);        } catch (Exception e) {            LOGGER.error("Error bulk index", e);        }    }         // sample data set implementation ...     }

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

@Bean@ConditionalOnProperty("initial-import.enabled")public SampleDataSet dataSet() {    return new SampleDataSet();}

6.查看数据并运行查询

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

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

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

c7134c47b39e58563f84bab16b4240a9.png

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

a22f2fb9dc2f4cfae604d54efba9c198.png

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

c1d757a27eff1aecff8d237c6d0d74ab.png

7.测试

好的,我们已经完成开发并在大数据集上执行了一些手动测试。现在,是时候创建一些在内置时间运行的集成测试了。我们可以使用允许在JUnit测试期间自动使用数据库启动Docker容器的库– Testcontainers。有关此库的更多信息,请访问其站。幸运的是,Testcontainers支持Elasticsearch。要在测试范围内启用它,您首先需要包括以下对您的依赖pom.xml:

    org.testcontainers    elasticsearch    1.11.1    test

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

@RunWith(SpringRunner.class)@SpringBootTest@FixMethodOrder(MethodSorters.NAME_ASCENDING)public class EmployeeRepositoryTest {     @ClassRule    public static ElasticsearchContainer container = new ElasticsearchContainer();    @Autowired    EmployeeRepository repository;     @BeforeClass    public static void before() {        System.setProperty("spring.data.elasticsearch.cluster-nodes", container.getContainerIpAddress() + ":" + container.getMappedPort(9300));    }     @Test    public void testAdd() {        Employee employee = new Employee();        employee.setId(1L);        employee.setName("John Smith");        employee.setAge(33);        employee.setPosition("Developer");        employee.setDepartment(new Department(1L, "TestD"));        employee.setOrganization(new Organization(1L, "TestO", "Test Street No. 1"));        employee = repository.save(employee);        Assert.assertNotNull(employee);    }     @Test    public void testFindAll() {        Iterable employees = repository.findAll();        Assert.assertTrue(employees.iterator().hasNext());    }     @Test    public void testFindByOrganization() {        List employees = repository.findByOrganizationName("TestO");        Assert.assertTrue(employees.size() > 0);    }     @Test    public void testFindByName() {        List employees = repository.findByName("John Smith");        Assert.assertTrue(employees.size() > 0);    } }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值