Java操作Elasticsearch的实用指南

失重外太空. 2024-10-04 10:35:01 阅读 95

Java操作Elasticsearch的实用指南

一、创建索引二、增删改查

一、创建索引

在ElasticSearch中索引相当于mysql中的表,mapping相当于表结构,所以第一步我们要先创建索引。

假设我们有一张文章表的数据需要同步到ElasticSearch,首先需要根据数据库表创建ES的索引结构。

<code>-- 文章表

create table if not exists post

(

id bigint auto_increment comment 'id' primary key,

title varchar(512) null comment '标题',

content text null comment '内容',

tags varchar(1024) null comment '标签列表(json 数组)',

thumbNum int default 0 not null comment '点赞数',

favourNum int default 0 not null comment '收藏数',

userId bigint not null comment '创建用户 id',

createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',

updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',

isDelete tinyint default 0 not null comment '是否删除',

index idx_userId (userId)

) comment '帖子' collate = utf8mb4_unicode_ci;

ElasticSearch的索引结构:

aliases:别名(为了方便后续数据迁移)字段类型是text,这个字段可以被分词,可模糊查询;字段类型是keyword,只能完全匹配,精确查询。analyzer(存储时生效的分词器):用ik_max_word,拆的更碎、索引更多,更有可能被搜出来search analyzer (查询时生效的分词器):用ik_smart,更偏向于用户想要搜的分词。

PUT post

{

"aliases": {

"post": { }

},

"mappings": {

"properties": {

"title": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_smart",

"fields": {

"keyword": {

"type": "keyword",

"ignore_above": 256

}

}

},

"content": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_smart",

"fields": {

"keyword": {

"type": "keyword",

"ignore_above": 256

}

}

},

"tags": {

"type": "keyword"

},

"userId": {

"type": "keyword"

},

"createTime": {

"type": "date"

},

"updateTime": {

"type": "date"

},

"isDelete": {

"type": "keyword"

}

}

}

}

在这里插入图片描述

二、增删改查

使用java客户端进行增删改查,第一步导入依赖。

<code> <!-- elasticsearch-->

<dependency>

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

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

</dependency>

第一种方式: ElasticsearchRepository<PostEsDTO,Long>,默认提供了简单的增删改查,多用于可预期的、相对没那么复杂的查询、自定义查询。

在这里插入图片描述

<code> @Test

void testSelect() { -- -->

System.out.println(postEsDao.count());

Page<PostEsDTO> PostPage = postEsDao.findAll(

PageRequest.of(0, 5, Sort.by("createTime")));

List<PostEsDTO> postList = PostPage.getContent();

System.out.println(postList);

}

@Test

void testAdd() {

PostEsDTO postEsDTO = new PostEsDTO();

postEsDTO.setId(1L);

postEsDTO.setTitle("我是章三");

postEsDTO.setContent("张三学习java,学习使我快乐!");

postEsDTO.setTags(Arrays.asList("java", "python"));

postEsDTO.setUserId(1L);

postEsDTO.setCreateTime(new Date());

postEsDTO.setUpdateTime(new Date());

postEsDTO.setIsDelete(0);

postEsDao.save(postEsDTO);

System.out.println(postEsDTO.getId());

}

@Test

void testFindById() {

Optional<PostEsDTO> postEsDTO = postEsDao.findById(1L);

System.out.println(postEsDTO);

}

@Test

void testCount() {

System.out.println(postEsDao.count());

}

@Test

void testFindByCategory() {

List<PostEsDTO> postEsDaoTestList = postEsDao.findByUserId(1L);

System.out.println(postEsDaoTestList);

}

ES 中,_开头的字段表示系统默认字段,比如 _id,如果系统不指定,会自动生成。但是不会在surce 字段中补充 id 的值,所以建议大家手动指定。

支持根据方法名自动生成方法,比如:

ListcPostEsDTO> findByTitle(String title);

第二种方式: Spring 默认给我们提供的提作 es 的客户端对象 ElasticsearchRestTemplate,也提供了增制改查,它的增删改查更灵活,适用于更复杂的操作。

ES的搜索条件:

GET /_search

{

"query": {

"bool": { 组合条件

"must": [ 必须都满足

{ "match": { "title": "Search" }}, 模糊查询

{ "match": { "content": "Elasticsearch" }}

],

"filter": [

{ "term": { "status": "published" }}, 精确查询

{ "range": { "publish_date": { "gte": "2015-01-01" }}} 范围查询

],

"should" : [

{ "term" : { "tags" : "env1" } },

{ "term" : { "tags" : "deployed" } }

],

"minimum_should_match" : 1, 包含匹配,最少匹配1条

"boost" : 1.0

}

}

}

对于复杂的查询,建议使用第二种方式。

//依赖注入

@Resource

private ElasticsearchRestTemplate elasticsearchRestTemplate;

三个步骤:

1、取参数

2、把参数组合为ES支持的搜索条件

3、从返回值中取结果

Long id = postQueryRequest.getId();

Long notId = postQueryRequest.getNotId();

String searchText = postQueryRequest.getSearchText();

String title = postQueryRequest.getTitle();

String content = postQueryRequest.getContent();

List<String> tagList = postQueryRequest.getTags();

List<String> orTagList = postQueryRequest.getOrTags();

Long userId = postQueryRequest.getUserId();

// es 起始页为 0

long current = postQueryRequest.getCurrent() - 1;

long pageSize = postQueryRequest.getPageSize();

String sortField = postQueryRequest.getSortField();

String sortOrder = postQueryRequest.getSortOrder();

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

// 过滤

boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", 0));

if (id != null) {

boolQueryBuilder.filter(QueryBuilders.termQuery("id", id));

}

if (notId != null) {

boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", notId));

}

if (userId != null) {

boolQueryBuilder.filter(QueryBuilders.termQuery("userId", userId));

}

// 必须包含所有标签

if (CollectionUtils.isNotEmpty(tagList)) {

for (String tag : tagList) {

boolQueryBuilder.filter(QueryBuilders.termQuery("tags", tag));

}

}

// 包含任何一个标签即可

if (CollectionUtils.isNotEmpty(orTagList)) {

BoolQueryBuilder orTagBoolQueryBuilder = QueryBuilders.boolQuery();

for (String tag : orTagList) {

orTagBoolQueryBuilder.should(QueryBuilders.termQuery("tags", tag));

}

orTagBoolQueryBuilder.minimumShouldMatch(1);

boolQueryBuilder.filter(orTagBoolQueryBuilder);

}

// 按关键词检索

if (StringUtils.isNotBlank(searchText)) {

boolQueryBuilder.should(QueryBuilders.matchQuery("title", searchText));

// boolQueryBuilder.should(QueryBuilders.matchQuery("description", searchText));

boolQueryBuilder.should(QueryBuilders.matchQuery("content", searchText));

boolQueryBuilder.minimumShouldMatch(1);

}

// 按标题检索

if (StringUtils.isNotBlank(title)) {

boolQueryBuilder.should(QueryBuilders.matchQuery("title", title));

boolQueryBuilder.minimumShouldMatch(1);

}

// 按内容检索

if (StringUtils.isNotBlank(content)) {

boolQueryBuilder.should(QueryBuilders.matchQuery("content", content));

boolQueryBuilder.minimumShouldMatch(1);

}

// 排序

SortBuilder<?> sortBuilder = SortBuilders.scoreSort();

if (StringUtils.isNotBlank(sortField)) {

sortBuilder = SortBuilders.fieldSort(sortField);

sortBuilder.order(CommonConstant.SORT_ORDER_ASC.equals(sortOrder) ? SortOrder.ASC : SortOrder.DESC);

}

// 分页

PageRequest pageRequest = PageRequest.of((int) current, (int) pageSize);

// 构造查询

NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)

.withPageable(pageRequest).withSorts(sortBuilder).build();

SearchHits<PostEsDTO> searchHits = elasticsearchRestTemplate.search(searchQuery, PostEsDTO.class);

后记

👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。