elasticsearch使用
1、选择
1、ElasticsearchRestTemplate是spring 对官方High Level REST Client的封装。
2、ElasticSearch 8.x 弃用了 High Level REST Client,移除了 Java Transport Client,推荐使用 Elasticsearch Java API (后续使用8的建议使用Elasticsearch Java API )
2、ElasticsearchRestTemplate的使用
(1)实体类
@Data
@Document(indexName = "stu", shards = 3, replicas = 0)
public class StuEntity {
@Id
private Long stuId;
@Field(store = true)
private String name;
@Field(store = true)
private Integer age;
@Field(store = true, type = FieldType.Keyword)
private String sign;
@Field(store = true)
private String description;
}
(2)操作
(2.1)普通的增
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Test
public void add() {
StuEntity stu = new StuEntity();
stu.setStuId(1005L);
stu.setName("iron man");
stu.setAge(54);
stu.setSign("I am iron man");
stu.setDescription("I have a iron army");
elasticsearchRestTemplate.save(stu);
}
(2.2)普通的查
package com.huyonghao.esapi;
import com.huyonghao.esapi.model.Content;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import java.util.List;
@SpringBootTest
class EsApiApplicationTests {
@Autowired
private ElasticsearchRestTemplate restTemplate;
@Test
void jdHighLight() {
// 高亮
HighlightBuilder highlightBuilder = new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>").field("title");
// 分页功能实现 5页
Pageable pageable = PageRequest.of(0, 5);
// 排序功能实现
FieldSortBuilder fieldSortBuilder = new FieldSortBuilder("_score");
// 条件查询 Match条件
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("title", "Lebron");
// Query对象 建造者模式 其中的分页和排序同样看代码可知。
NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(matchQueryBuilder).withFields("title", "id", "img", "price")
.withHighlightBuilder(highlightBuilder).withPageable(pageable).withSort(fieldSortBuilder).build();
// 查询
SearchHits<Content> hits = restTemplate.search(query, Content.class);
List<SearchHit<Content>> searchHits = hits.getSearchHits();
System.out.println("一共" + searchHits.size() + "个");
for (SearchHit<Content> searchHit : searchHits) {
// 遍历返回命中结果
Content content = searchHit.getContent();
// 获取高亮字段
List<String> titleHighLightList = searchHit.getHighlightField("title");
// 将高亮字段替换查询出的对象中的title
if (titleHighLightList != null) {
content.setTitle(titleHighLightList.get(0));
}
System.out.println(content);
}
}
}
(2.3)普通的改
@Test
public void update() {
StuEntity stu = new StuEntity();
stu.setStuId(1005L);
stu.setName("iron manss");
stu.setAge(100);
stu.setSign("I am iron man");
stu.setDescription("I have a iron army");
System.out.println(JSON.toJSONString(stu));
// 创建Document对象
// 第一种方式
Document document = Document.create();
// 将修改的内容塞进去
document.putAll(JSON.parseObject(JSON.toJSONString(stu), Map.class));
// 第二种方式
Document document1 = Document.parse(JSON.toJSONString(stu));
// 第三种方式
Document document2 = Document.from(JSON.parseObject(JSON.toJSONString(stu), Map.class));
// 构造updateQuery
UpdateQuery updateQuery = UpdateQuery.builder("1")
// 如果不存在就新增,默认为false
.withDocAsUpsert(true)
.withDocument(Document.parse(JSON.toJSONString(stu)))
.build();
elasticsearchRestTemplate.update(updateQuery, IndexCoordinates.of("stu"));
}
(2.4)普通的删
@Test
public void delete() {
StuEntity stu = new StuEntity();
stu.setStuId(1005L);
stu.setName("iron man");
stu.setAge(54);
stu.setSign("I am iron man");
stu.setDescription("I have a iron army");
elasticsearchRestTemplate.delete(stu);
}
查询就调用elasticsearchRestTemplate中SearchOperations`的search方法。
在search的各种方法中都需要传入Query。Spring Data Elasticsearch中Query的实现类CriteriaQuery, StringQuery and NativeSearchQuery
CriteriaQuery基于查询的查询允许创建查询来搜索数据,而无需了解 Elasticsearch 查询的语法或基础知识。它们允许用户通过简单地链接和组合指定搜索文档必须满足的条件的对象来生成查询
StringQuery使用json字符串来构建查询条件。就和Repository中@Query注解中的那个json字符串一样。
NativeSearchQuery用于复杂查询。
(2.5)批量操作
public class ElasticsearchUtil {
/**
* 批量插入的数据长度大小
*/
private final int PAGE_SIZE = 150000;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
/**
* 批量插入数据
* @return
*/
public int bulkIndex(String indexName,String indexType,List<BaseEsEntity> dataList){
int counter = 0;
checkData(indexName,indexType,dataList);
//判断索引是否存在
if (!elasticsearchTemplate.indexExists(indexName)) {
elasticsearchTemplate.createIndex(indexName);
}
List<IndexQuery> indexQueries = convertData(dataList,indexName,indexType);
elasticsearchTemplate.bulkIndex(indexQueries);
log.info("bulkIndex counter : " + indexQueries.size());
counter = indexQueries.size();
indexQueries.clear();
dataList.clear();
elasticsearchTemplate.refresh(indexName);
return counter;
}
private void checkData(String indexName,String indexType,List<BaseEsEntity> dataList){
if(StringUtils.isBlank(indexName) || StringUtils.isBlank(indexType)){
throw new RuntimeException("indexName or indexType can not be null");
}
if(CollectionUtils.isEmpty(dataList)){
throw new RuntimeException(String.format("保存的数据不能为空,data size 长度{%d}", dataList.size()));
}
if(dataList.size() > PAGE_SIZE){
throw new RuntimeException(String.format("data size 必须小于{%d},当前长度{%d}", PAGE_SIZE, dataList.size()));
}
}
private List<IndexQuery> convertData(List<BaseEsEntity> dataList,String indexName,String indexType){
List<IndexQuery> queries = new ArrayList<>();
for (BaseEsEntity esEntity : dataList) {
IndexQuery indexQuery = new IndexQuery();
indexQuery.setId(esEntity.getId());
indexQuery.setSource(JSONObject.toJSONString(esEntity));
indexQuery.setIndexName(indexName);
indexQuery.setType(indexType);
queries.add(indexQuery);
}
return queries;
}
}
一次插入15万