本主要介绍ElasticSearch 和 SpringBoot 的整合 ,对您有帮助的话,点个关注哦

ElastSearch 介绍

  • ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。
  • Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
解决了什么问题

我们建立一个网站或应用程序,并要添加搜索功能,但是想要完成搜索工作的创建是非常困难的。我们希望搜索解决方案要运行速度快,我们希望能有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP来索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并扩展到数百台,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。因此我们利用Elasticsearch来解决所有这些问题及可能出现的更多其它问题。

具体elasticsearch相关问题可以去elastic中文社区查看。

环境准备

  • Java版本:JDK8
  • elasticsearch: ES 6.8
  • SpringBoot :2.1.7.RELEASE

1.启动elasticsearch的 *.bat文件。

2.新建项目,pom文件中加入elasticsearch依赖,完整pom如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.spiritmark.boot</groupId>
<artifactId>ElastSearch-Boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ElastSearch-Boot</name>
<description>elasticsearch</description> <properties>
<java.version>1.8</java.version>
<testng.version>6.14.2</testng.version>
<spring-cloud-dependencies.version>Greenwich.RELEASE</spring-cloud-dependencies.version>
<kibana-logging-spring-boot-starter.version>1.2.4</kibana-logging-spring-boot-starter.version>
<fastjson.version>1.2.47</fastjson.version>
<alarm-spring-boot-starter.version>1.0.15-SNAPSHOT</alarm-spring-boot-starter.version>
</properties> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
<!-- 日期处理 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!--FastJson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency> <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

application.yml 配置文件如下:

server:
port: 8080
servlet:
context-path: /search
spring:
application:
name: search
data:
elasticsearch:
cluster-name: my-cluster
cluster-nodes: localhost:9300
jackson:
default-property-inclusion: non_null logging:
file: application.log
path: .
level:
root: info
com.spiritmark.store.client: DEBUG index-entity:
configs:
- docCode: store
indexName: store
type: base
documentPath: com.spiritmark.document.StoreDocument

spring.data.elasticsearch.cluster-name:集群名称

spring.data.elasticsearch.cluster-nodes:集群节点地址列表,多个节点用英文逗号(,)分隔

创建文档实体映射

创建一个实体类,然后通过注解来声明字段的映射属性。

Spring提供的注解有@Document@Id@Field,其中@Document作用在类,@Id@Field作用在成员变量,@Id 标记一个字段作为id主键。

package com.spiritmark.boot;

import com.spiritmark.document.store.*;
import com.spiritmark.search.annotation.DefinitionQuery;
import com.spiritmark.search.enums.QueryTypeEnum;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType; import java.util.List; /**
*
* @author SpiritMark
* @date Create at 19:31 2019/8/22
*/
@Document(indexName = "store", type = "base")
@Data
@DefinitionQuery(key = "page", type = QueryTypeEnum.IGNORE)
@DefinitionQuery(key = "size", type = QueryTypeEnum.IGNORE)
@DefinitionQuery(key = "q", type = QueryTypeEnum.FULLTEXT)
public class StoreDocument { @Id
@DefinitionQuery(type = QueryTypeEnum.IN)
@DefinitionQuery(key = "id", type = QueryTypeEnum.IN)
@Field(type = FieldType.Keyword)
private String id; /**
* 基础信息
*/
@Field(type = FieldType.Object)
private StoreBaseInfo baseInfo; /**
* 标签
*/
@Field(type = FieldType.Nested)
@DefinitionQuery(key = "tagCode", mapped = "tags.key", type = QueryTypeEnum.IN)
@DefinitionQuery(key = "tagValue", mapped = "tags.value", type = QueryTypeEnum.AND)
@DefinitionQuery(key = "_tagValue", mapped = "tags.value", type = QueryTypeEnum.IN)
private List<StoreTags> tags; }
注解详解 :

Spring Data通过注解来声明字段的映射属性,有下面的三个注解:

  • @Document 作用在类,标记实体类为文档对象,一般有两个属性
  • indexName:对应索引库名称
  • type:对应在索引库中的类型
  • shards:分片数量,默认5
  • replicas:副本数量,默认1
  • @Id 作用在成员变量,标记一个字段作为id主键
  • @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
  • type:字段类型,是枚举:FieldType,可以是text、long、short、date、integer、object等
  • text:存储数据时候,会自动分词,并生成索引
  • keyword:存储数据时候,不会分词建立索引
  • Numerical:数值类型,分两类
  • 基本数据类型:long、interger、short、byte、double、float、half_float
  • 浮点数的高精度类型:scaled_float

    需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
  • Date:日期类型
  • elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
  • index:是否索引,布尔类型,默认是true
  • store:是否存储,布尔类型,默认是false
  • analyzer:分词器名称,这里的ik_max_word即使用ik分词器

分析核心 类 ElasticsearchTemplate

ElasticsearchTemplate 提供了四个createIndex() 方法来创建索引,可以根据类的信息自动生成,也可以手动指定indexName和Settings

创建索引源码 :

@Override
public <T> boolean createIndex(Class<T> clazz) {
return createIndexIfNotCreated(clazz);
} @Override
public boolean createIndex(String indexName) {
Assert.notNull(indexName, "No index defined for Query");
return client.admin().indices().create(Requests.createIndexRequest(indexName)).actionGet().isAcknowledged();
}
@Override
public boolean createIndex(String indexName, Object settings) {
CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(indexName);
if (settings instanceof String) {
createIndexRequestBuilder.setSettings(String.valueOf(settings), Requests.INDEX_CONTENT_TYPE);
} else if (settings instanceof Map) {
createIndexRequestBuilder.setSettings((Map) settings);
} else if (settings instanceof XContentBuilder) {
createIndexRequestBuilder.setSettings((XContentBuilder) settings);
}
return createIndexRequestBuilder.execute().actionGet().isAcknowledged();
} @Override
public <T> boolean createIndex(Class<T> clazz, Object settings) {
return createIndex(getPersistentEntityFor(clazz).getIndexName(), settings);
}

删除索引源码

ElasticsearchTemplate提供了2个deleteIndex()方法来删除索引

@Override
public <T> boolean deleteIndex(Class<T> clazz) {
return deleteIndex(getPersistentEntityFor(clazz).getIndexName());
} @Override
public boolean deleteIndex(String indexName) {
Assert.notNull(indexName, "No index defined for delete operation");
if (indexExists(indexName)) {
return client.admin().indices().delete(new DeleteIndexRequest(indexName)).actionGet().isAcknowledged();
}
return false;
}

创建映射源码:

ElasticsearchTemplate提供了三个putMapping()方法来创建映射

@Override
public <T> boolean putMapping(Class<T> clazz) {
if (clazz.isAnnotationPresent(Mapping.class)) {
String mappingPath = clazz.getAnnotation(Mapping.class).mappingPath();
if (!StringUtils.isEmpty(mappingPath)) {
String mappings = readFileFromClasspath(mappingPath);
if (!StringUtils.isEmpty(mappings)) {
return putMapping(clazz, mappings);
}
} else {
LOGGER.info("mappingPath in @Mapping has to be defined. Building mappings using @Field");
}
}
ElasticsearchPersistentEntity<T> persistentEntity = getPersistentEntityFor(clazz);
XContentBuilder xContentBuilder = null;
try { ElasticsearchPersistentProperty property = persistentEntity.getRequiredIdProperty(); xContentBuilder = buildMapping(clazz, persistentEntity.getIndexType(),
property.getFieldName(), persistentEntity.getParentType());
} catch (Exception e) {
throw new ElasticsearchException("Failed to build mapping for " + clazz.getSimpleName(), e);
}
return putMapping(clazz, xContentBuilder);
} @Override
public <T> boolean putMapping(Class<T> clazz, Object mapping) {
return putMapping(getPersistentEntityFor(clazz).getIndexName(), getPersistentEntityFor(clazz).getIndexType(),
mapping);
} @Override
public boolean putMapping(String indexName, String type, Object mapping) {
Assert.notNull(indexName, "No index defined for putMapping()");
Assert.notNull(type, "No type defined for putMapping()");
PutMappingRequestBuilder requestBuilder = client.admin().indices().preparePutMapping(indexName).setType(type);
if (mapping instanceof String) {
requestBuilder.setSource(String.valueOf(mapping), XContentType.JSON);
} else if (mapping instanceof Map) {
requestBuilder.setSource((Map) mapping);
} else if (mapping instanceof XContentBuilder) {
requestBuilder.setSource((XContentBuilder) mapping);
}
return requestBuilder.execute().actionGet().isAcknowledged();
}

测试

@Test
public void testCreate() {
System.out.println(elasticsearchTemplate.createIndex(StoreDocument.class));
System.out.println(elasticsearchTemplate.putMapping(StoreDocument.class));
}

Repository 接口

另一种则是通过Repository接口。Spring提供的ES的Repository接口为ElasticsearchCrudRepository,所以我们就可以直接定义额新的接口,然后实现ElasticsearchCrudRepository 即可:

package com.spiritmark.boot;

import com.taoche.document.StoreDocument;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; /**
* 门店Repository
* @author 李锋镝
* @date Create at 09:30 2019/8/23
*/
public interface StoreRepository extends ElasticsearchRepository<StoreDocument, String> { }

测试

@Test
public void testSave() { StoreDocument storeDocument = new StoreDocument();
storeDocument.setId("1");
StoreBaseInfo baseInfo = new StoreBaseInfo();
baseInfo.setStoreId("1");
baseInfo.setCreatedTime(DateTime.now());
storeDocument.setBaseInfo(baseInfo); storeRepository.save(storeDocument);
}
查询

ES的主要功能就是查询,ElasticsearchRepository 也提供了基本的查询接口,比如findById()、findAll()、findAllById()、search()等方法;当然也可以使用Spring Data提供的另外一个功能:Spring Data JPA——通过方法名创建查询,当然需要遵循一定的规则,比如你的方法名叫做findByTitle(),那么它就知道你是根据title查询,然后自动帮你完成,这里就不仔细说了。

上边说的基本能满足一般的查询,复杂一点的查询就无能为力了,这就需要用到自定义查询,这里可以查看我的另一篇博客SpringBoot使用注解的方式构建Elasticsearch查询语句,实现多条件的复杂查询,这里边有详细的说明。

SpringBoot从入门到精通教程(八)的更多相关文章

  1. SpringBoot从入门到精通教程(二)

    SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖 ...

  2. SpringBoot从入门到精通教程(七)

    今天,我们继续讲SpringBoot整合Redis ,也就缓存,它将与我们的Springboot整合 Redis 简介 Redis 是当前比较热门的NOSQL系统之一,它是一个开源的使用ANSI c语 ...

  3. SpringBoot从入门到精通教程(六)

    之前学了,这么多东西 thyemeaf .MyBatis 还有 配置文件等等,今天我们就来做一个小案例 CRUD,程序员的必备 项目结构 pom.xml <!-- mybatis 相关依赖 -- ...

  4. SpringBoot从入门到精通教程(三)

    在上一篇中,我们已经讲了,SpringBoot 如何构建项目,和SpringBoot的HelloWorld, 那这一节我们继续讲 Thymeleaf Thymeleaf 官网: Thymeleaf T ...

  5. SpringBoot从入门到精通教程(一)

    写在前面的话: 在很早之前,记笔记时候,我就一直在思考一个问题,我记笔记是为了什么,我一直想不明白 ,后面发现技术跟新迭代的速度实在太快了,笔记刚纪完,技术又跟新了,于是我想了想干脆边写博客,边记笔记 ...

  6. SpringBoot从入门到精通教程(五)

    上节,我们讲了 SpringBoot 如何使用MyBatis 今天我们讲讲 Springboot Logo自定义的问题, 我们在启动 SpringBoot 时,控制台会打印 SpringBoot Lo ...

  7. SpringBoot从入门到精通教程(四)

    前端时间整合SSM ,发现了一个现象,在整合的时候 配置文件过于复杂. 1.建工程,建目录,导入jar包. 2.配置 数据源 映射信息 等等 ... 3. 还有 各种 拦截器,控制器 ,头都大了... ...

  8. 深入浅出!springboot从入门到精通,实战开发全套教程!

    前言 之前一直有粉丝想让我出一套springboot实战开发的教程,我这边总结了很久资料和经验,在最近总算把这套教程的大纲和内容初步总结完毕了,这份教程从springboot的入门到精通全部涵盖在内, ...

  9. Spring Boot从入门到精通(八)日志管理实现和配置信息分析

    Spring Boot对日志的处理,与平时我们处理日志的方式完全一致,它为Java Util Logging.Log4J2和Logback提供了默认配置.对于每种日志都预先配置使用控制台输出和可选的文 ...

随机推荐

  1. CorelDRAW文件损坏的几种解决方法

    以前做好的CorelDRAW文件突然打不开了,或者是死机.非法操作等原因造成CorelDRAW文件损坏,有时打开源文件发现一片空白,源文件保存损坏无法打开怎么办?此时不要着急,你可以试试以下几种办法帮 ...

  2. 加密PDF文件,提高文件安全性

    PDF文件的一大优点是可以设置文件的安全性,不仅可以通过证书加密的形式加密文件,还可以通过pdfFactory来设置密码的形式加密文件. 我们可以通过两种方式开启"PDF加密"来为 ...

  3. Logstash使用mongodb插件报错: ArgumentError: wrong number of arguments (given 2, expected 1)

    目录 背景 安装插件过程 背景 今天在使用logstash收集日志存储到mongodb的安装过程遇到了个错误,记录下来,错误就是下面这样: 配置文件很简单,由于是测试环境,命令行传入日志输入由ruby ...

  4. 墨振文档__UnitTest断言

    unittest 断言方法 断言:自动化测试主要用于对流程来进行测试,断言就是自动化测试中的预期结果与实际结果的对比.

  5. netty&websocket

    1.先判断是不是http 消息,不是返回400,是则remove之前添加的http组件,动态添加websocket组件 添加WebSocket Encoder和WebSocket Decoder之后, ...

  6. layer 父弹窗获取子弹窗内的dom节点元素和变量

    1 var body = layer.getChildFrame('body', index); //获取子弹窗的dom节点 2 3 var iframeWin = window[layero.fin ...

  7. 5、pgpool-II高可用性(一)数据库的高可用性

    官网示例 一.实现原理 使用 pgpool-II 软件:我们常用来实现流复制的高可用性:备库只读的,不可写:就是当主库出现问题时:需要把备库自动激活为主库:来接管服务. 这在其他高可用软件也有这功能, ...

  8. Django----Serializer序列化

    serializer的两大特征 1.校检数据 2.序列化 首先创建apps/Serializer.py 在序列化里面导包 from rest_framework import serializers ...

  9. 老猿学5G扫盲贴:3GPP规范中与计费相关的主要规范文档列表及下载链接

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在<老猿学5G扫盲贴:3GPP规范中部分与计 ...

  10. 老猿学5G随笔:5G核心网中与用户数据相关的NF功能体UDM、AUSF、PCF、UDR

    在业务支撑工作中,与核心网主要的交互包括用户数据管理(含签约关系.策略数据),5G核心网中与用户数据相关的NF功能体包括UDM.AUSF和PCR以及UDR,在此只简单介绍这些NF的功能: UDM:统一 ...