本主要介绍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. Guitar Pro吉他指弹入门——特殊调弦

    本期文章中,我们将通过吉他打谱软件Guitar Pro 7来向大家讲解指弹曲目中所涉及的特殊调弦. 作为一个吉他手,在练琴的时候总会遇到各种各样的问题,比如说鼓手不肯跟你合作(因为打鼓往往不能露脸), ...

  2. 用Camtasia设计微课视频封面,让课程更加高大上

    在网络时代,尤其现在疫情影响只能线上学习,微课的应用前景已经越来越广了.但是想把微课做好,只有内容与录制精细是不够的,还需要一个精美的封面来吸引学生.接下来,小编就用微课制作软件Camtasia 20 ...

  3. 语音识别2 -- Listen,Attend,and Spell (LAS)

    LAS是Listen(Encoder),Attend,和Spell(Decoder)的简称 第一个步骤Listen(Encoder) listen的作用是输入一段语音信号,输出一段向量,去掉语音中的杂 ...

  4. 【Vue】VUE源码中的一些工具函数

    Vue源码-工具方法 /* */ //Object.freeze()阻止修改现有属性的特性和值,并阻止添加新属性. var emptyObject = Object.freeze({}); // th ...

  5. P5656 【模板】二元一次不定方程(exgcd)

    还不会 exgcd 的请移步窝的学习笔记,这里只讲怎么搞出烦人的答案. 在 \(a,b\) 两者互质的情况下,二元一次不定方程的通解:\(a(x+db)+b(y+da)=c\). 所以要先将 \(a, ...

  6. 使用Python切片赋值

    解释器下运行以下代码:list1 = [4,5,6,7,8,9] list1[2:5] = ['a','b','c']结果是:[4, 5, 'a', 'b', 'c', 9]

  7. Debian10快速部署DHCP服务

    前言 DHCP(动态主机配置协议)是一个局域网的网络协议.指的是由服务器控制一段IP地址范围,客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码. 进日,想提升一下自己的技术水平,于是就做 ...

  8. LaTeX的字体字号设置

    字体属性: 字体族代码及注释: 显示效果: 字体系列设置及字体形状设置代码及注释: 显示效果: 字体大小及中文字号的设置代码及注释: 显示效果: ctex文档有关中文字号的排版: ctex文档的打开方 ...

  9. Java多线程中的wait/notify通信模式

    前言 最近在看一些JUC下的源码,更加意识到想要学好Java多线程,基础是关键,比如想要学好ReentranLock源码,就得掌握好AQS源码,而AQS源码中又有很多Java多线程经典的一些应用:再比 ...

  10. 第三十四章、PyQt中的输入部件:QComboBox组合框功能详解

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 Designer中输入工具部件中的Combo Box组合框与 ...