springboot中使用ElasticSearch的详细教程

网友投稿 903 2023-01-23

springboot中使用ElasticSearch的详细教程

springboot中使用ElasticSearch的详细教程

新建项目

新建一个springboot项目springboot_es用于本次与ElasticSearch的整合,如下图

引入依赖

修改我们的pom.xml,加入spring-boot-starter-data-elasticsearch

org.springframework.boot

spring-boot-starter-data-elasticsearch

编写配置文件

由于ElasticSearch从7.x版本开始淡化TransportClient甚至于在8.x版本中遗弃,所以spring data elasticsearch推荐我们使用rest客户端RestHingLevelClient(端口号使用9200)以及接口ElasticSearchRespositoy。

RestHighLevelClient 更强大,更灵活,但是不能友好的操作对象

ElasticSearchRepository 对象操作友好

首先我们编写配置文件如下

/**

* ElasticSearch Rest Client config

* @author Christy

* @date 2021/4/29 19:40

**/

@Configuration

public class ElasticSearchRestClientConfig extends AbstractElasticsearchConfiguration{

@Override

@Bean

public RestHighLevelClient elasticsearchClient() {

final ClientConfiguration clientConfiguration = ClientConfiguration.builder()

.connectedTo("192.168.8.101:9200")

.build();

return RestClients.create(clientConfiguration).rest();

}

}

springboot操作ES

RestHighLevelClient方式

有了上面的rest client,我们就可以在其他的地方注入该客户端对ElasticSearch进行操作。我们新建一个测试文件,使用客户端对ElasticSearch进行基本的操作

1.注入RestClient

/**

* ElasticSearch Rest client操作

*

* RestHighLevelClient 更强大,更灵活,但是不能友好的操作对象

* ElasticSearchRepository 对象操作友好

*

* 我们使用rest client 主要测试文档的操作

* @Author Christy

* @Date 2021/4/29 19:51

**/

@SpringBootTest

public class TestRestClient {

// 复杂查询使用:比如高亮查询

@Autowired

private RestHighLevelClient restHighLevelClient;

}

2.插入一条文档

/**

* 新增一条文档

* @author Christy

* @date 2021/4/29 20:17

*/

@Test

public void testAdd() throws IOException {

/**

* 向ES中的索引christy下的type类型中添加一天文档

*/

IndexRequest indexRequest = new IndexRequest("christy","user","11");

indexRequest.source("{\"name\":\"齐天大圣孙悟空\",\"age\":685,\"bir\":\"1685-01-01\",\"introduce\":\"花果山水帘洞美猴王齐天大圣孙悟空是也!\"," +

"\"address\":\"花果山\"}", XContentType.jsON);

IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);

System.out.println(indexResponse.status());

}

我们可以看到文档插入成功,我们去kibana中查询该条文档

完全没有问题的。

3.删除一条文档

/**

* 删除一条文档

* @author Christy

* @date 2021/4/29 20:18

*/

@Test

public void deleteDoc() throws IOException {

// 我们把特朗普删除了

DeleteRequest deleteRequest = new DeleteRequest("christy","user","rYBNG3kBRz-Sn-2f3ViU");

DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);

System.out.println(deleteResponse.status());

}

}

4.更新一条文档

/**

* 更新一条文档

* @author Christy

* @date 2021/4/29 20:19

*/

@Test

public void updateDoc() throws IOException {

UpdateRequest updateRequest = new UpdateRequest("christy","user","p4AtG3kBRz-Sn-2fMFjj");

updateRequest.doc("{\"name\":\"调皮捣蛋的hardy\"}",XContentType.JSON);

UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);

System.out.println(updateResponse.status());

}

5.批量更新文档

/**

* 批量更新

* @author Christy

* @date 2021/4/29 20:42

*/

@Test

public void bulkUpdate() throws IOException {

BulkRequest bulkRequest = new BulkRequest();

// 添加

IndexRequest indexRequest = new IndexRequest("christy","user","13");

indexRequest.source("{\"name\":\"天蓬元帅猪八戒\",\"age\":985,\"bir\":\"1685-01-01\",\"introduce\":\"天蓬元帅猪八戒因调戏嫦娥被贬下凡\",\"address\":\"高老庄YNqwoQuLP\"}", XContentType.JSON);

bulkRequest.add(indexRequest);

// 删除

DeleteRequest deleteRequest01 = new DeleteRequest("christy","user","pYAtG3kBRz-Sn-2fMFjj");

DeleteRequest deleteRequest02 = new DeleteRequest("christy","user","uhTyGHkBExaVQsl4F9Lj");

DeleteRequest deleteRequest03 = new DeleteRequest("christy","user","C8zCGHkB5KgTrUTeLyE_");

bulkRequest.add(deleteRequest01);

bulkRequest.add(deleteRequest02);

bulkRequest.add(deleteRequest03);

// 修改

UpdateRequest updateRequest = new UpdateRequest("christy","user","10");

updateRequest.doc("{\"name\":\"炼石补天的女娲\"}",XContentType.JSON);

bulkRequest.add(updateRequest);

BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);

BulkItemResponse[] items = bulkResponse.getItems();

for (BulkItemResponse item : items) {

System.out.println(item.status());

}

}

在kibana中查询结果

6.查询文档

@Test

public void testSearch() throws IOException {

//创建搜索对象

SearchRequest searchRequest = new SearchRequest("christy");

//搜索构建对象

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

searchSourceBuilder.query(QueryBuilders.matchAllQuery())//执行查询条件

.from(0)//起始条数

.size(10)//每页展示记录

.postFilter(QueryBuilders.matchAllQuery()) //过滤条件

.sort("age", SortOrder.DESC);//排序

//创建搜索请求

searchRequest.types("user").source(searchSourceBuilder);

SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

System.out.println("符合条件的文档总数: "+searchResponse.getHits().getTotalHits());

System.out.println("符合条件的文档最大得分: "+searchResponse.getHits().getMaxScore());

SearchHit[] hits = searchResponse.getHits().getHits();

for (SearchHit hit : hits) {

System.out.println(hit.getSourceAsMap());

}

}

ElasticSearchRepository方式

1.准备工作

ElasticSearchRepository方式主要通过注解和对接口实现的方式来实现ES的操作,我们在实体类上通过注解配置ES索引的映射关系后,当实现了ElasticSearchRepository接口的类第一次操作ES进行插入文档的时候,ES会自动生成所需要的一切。但是该种方式无法实现高亮查询,想要实现高亮查询只能使用RestHighLevelClient

开始之前我们需要熟悉一下接口方式为我们提供的注解,以及编写一些基础的类

1.清空ES数据

2.了解注解

@Document: 代表一个文档记录

indexName: 用来指定索引名称

type: 用来指定索引类型

@Id: 用来将对象中id和ES中_id映射

@Field: 用来指定ES中的字段对应Mapping

type: 用来指定ES中存储类型

analyzer: 用来指定使用哪种分词器

3.新建实体类

/**

* 用在类上作用:将Emp的对象映射成ES中一条json格式文档

* indexName: 用来指定这个对象的转为json文档存入那个索引中 要求:ES服务器中之前不能存在此索引名

* type : 用来指定在当前这个索引下创建的类型名称

*

* @Author Christy

* @Date 2021/4/29 21:22

*/

@Data

@Document(indexName = "christy",type = "user")

public class User {

@Id //用来将对象中id属性与文档中_id 一一对应

private String id;

// 用在属性上 代表mapping中一个属性 一个字段 type:属性 用来指定字段类型 analyzer:指定分词器

@Field(type = FieldType.Text,analyzer = "ik_max_word")

private String name;

@Field(type = FieldType.Integer)

private Integer age;

@Field(type = FieldType.Date)

@JsonFormat(pattern = "yyyy-MM-dd")

private Date bir;

@Field(type = FieldType.Text,analyzer = "ik_max_word")

private String content;

@Field(type = FieldType.Text,analyzer = "ik_max_word")

private String address;

}

4.UserRepository

/**

* @Author Christy

* @Date 2021/4/29 21:23

**/

public interface

extends ElasticsearchRepository {

}

5.TestUserRepository

/**

* @Author Christy

* @Date 2021/4/29 21:51

**/

@SpringBootTest

public class TestUserRepository {

@Autowired

private UserRepository userRepository;

}

2.保存文档

@Test

public void testSaveAndUpdate(){

User user = new User();

// id初识为空,此操作为新增

user.setId(UUID.randomUUID().toString());

user.setName("唐三藏");

user.setBir(new Date());

user.setIntroduce("西方世界如来佛祖大弟子金蝉子转世,十世修行的好人,得道高僧!");

user.setAddress("大唐白马寺");

userRepository.save(user);

}

3.修改文档

@Test

public void testSaveAndUpdate(){

User user = new User();

// 根据id修改信息

user.setId("1666eb47-0bbf-468b-ab45-07758c741461");

user.setName("唐三藏");

user.setBir(new Date());

user.setIntroduce("俗家姓陈,状元之后。西方世界如来佛祖大弟子金蝉子转世,十世修行的好人,得道高僧!");

user.setAddress("大唐白马寺");

userRepository.save(user);

}

4.删除文档

repository接口默认提供了4种删除方式,我们演示根据id进行删除

@Test

public void deleteDoc(){

userRepository.deleteById("1666eb47-0bbf-468b-ab45-07758c741461");

}

5.检索一条记录

@Test

public void testFindOne(){

Optional optional = userRepository.findById("1666eb47-0bbf-468b-ab45-07758c741461");

System.out.println(optional.get());

}

6.查询所有

@Test

public void testFindAll(){

Iterable all = userRepository.findAll();

all.forEach(user-> YNqwoQuLPSystem.out.println(user));

}

7.排序

@Test

public void testFindAllSort(){

Iterable all = userRepository.findAll(Sort.by(Sort.Order.asc("age")));

all.forEach(user-> System.out.println(user));

}

8.分页

@Test

public void testFindPage(){

//PageRequest.of 参数1: 当前页-1

Page search = userRepository.search(QueryBuilders.matchAllQuery(), PageRequest.of(1, 1));

search.forEach(user-> System.out.println(user));

}

9.自定义查询

先给大家看一个表,是不是很晕_(¦3」∠)_

Keyword

Sample

Elasticsearch Query String

And

findByNameAndPrice

{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}

Or

findByNameOrPrice

{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}

Is

findByName

{"bool" : {"must" : {"field" : {"name" : "?"}}}}

Not

findByNameNot

{"bool" : {"must_not" : {"field" : {"name" : "?"}}}}

Between

findByPriceBetween

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

LessThanEqual

findByPriceLessThan

{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

GreaterThanEqual

findByPriceGreaterThan

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}

Before

findByPriceBefore

{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

After

findByPriceAfter

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}

Like

findByNameLike

{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}

StartingWith

findByNameStartingWith

{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}

EndingWith

findByNameEndingWith

{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}

Contains/Containing

findByNameContaining

{"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}

In

findByNameIn

(Collectionnames)

{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}

NotIn

findByNameNotIn

(Collectionnames)

{"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}

http:// Near

findByStoreNear

Not Supported Yet !

True

findByAvailableTrue

{"bool" : {"must" : {"field" : {"available" : true}}}}

False

findByAvailableFalse

{"bool" : {"must" : {"field" : {"available" : false}}}}

OrderBy

findByAvailable

TrueOrderByNameDesc

{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}

这个表格看起来复杂,实际上也不简单,但是确实很牛逼。我们只要按照上面的定义在接口中定义相应的方法,无须写实现就可实现我们想要的功能

举个例子,上面有个findByName是下面这样定义的

假如我们现在有个需求需要按照名字查询用户,我们可以在UserRepository中定义一个方法,如下

// 根据姓名查询

List findByName(String name);

系统提供的查询方法中findBy是一个固定写法,像上面我们定义的方法findByName,其中Name是我们实体类中的属性名,这个必须对应上。也就是说这个findByName不仅仅局限于name,还可以findByAddress、findByAge等等;

现在就拿findByName来讲,我们要查询名字叫唐三藏的用户

@Test

public void testFindByName(){

List userList = userRepository.findByName("唐三藏");

userList.forEach(user-> System.out.println(user));

}

其实就是框架底层直接使用下面的命令帮我们实现的查询

GET /christy/user/_search

{

"query": {

"bool": {

"must": [

{

"term": {

"name":"?"

}

}

]

}

}

}

10.高亮查询

我们上面说了,ElasticSearchRepository实现不了高亮查询,想要实现高亮查询还是需要使用RestHighLevelClient方式。最后我们使用rest clientl实现一次高亮查询

@Test

public void testHighLightQuery() throws IOException, ParseException {

// 创建搜索请求

SearchRequest searchRequest = new SearchRequest("christy");

// 创建搜索对象

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

searchSourceBuilder.query(QueryBuilders.termQuery("introduce", "唐僧")) // 设置查询条件

.from(0) // 起始条数(当前页-1)*size的值

.size(10) // 每页展示条数

.sort("age", SortOrder.DESC) // 排序

.highlighter(new HighlightBuilder().field("*").requireFieldMatch(false).preTags("").postTags("")); // 设置高亮

searchRequest.types("user").source(searchSourceBuilder);

SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

SearchHit[] hits = searchResponse.getHits().getHits();

List userList = new ArrayList<>();

for (SearchHit hit : hits) {

Map sourceAsMap = hit.getSourceAsMap();

User user = new User();

user.setId(hit.getId());

user.setAge(Integer.parseInt(sourceAsMap.get("age").toString()));

user.setBir(new SimpleDateFormat("yyyy-MM-dd").parse(sourceAsMap.get("bir").toString()));

user.setIntroduce(sourceAsMap.get("introduce").toString());

user.setName(sourceAsMap.get("name").toString());

user.setAddress(sourceAsMap.get("address").toString());

Map highlightFields = hit.getHighlightFields();

if(highlightFields.containsKey("name")){

user.setName(highlightFields.get("name").fragments()[0].toString());

}

if(highlightFields.containsKey("introduce")){

user.setIntroduce(highlightFields.get("introduce").fragments()[0].toString());

}

if(highlightFields.containsKey("address")){

user.setAddress(highlightFields.get("address").fragments()[0].toString());

}

userList.add(user);

}

userList.forEach(user -> System.out.println(user));

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:通软应用安全桌面要联网吗(通软应用安全桌面要联网吗怎么设置)
下一篇:混合app开发作品(混合app开发作品推荐)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~