我们前两章有写过整合es教程,但是那是使用spring data实现的,只能实现简单的es语句,复杂的语句我们推荐使用springboot
一、基本操作的实现
1.创建项目
?
2.添加依赖
项目目录如下:
?????????
上述搭建好项目后,添加json和es依赖
<!--json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.1</version>
</dependency>
?3.编写eneity
JobDetail:
package com.xupeng.es.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
/**
* [一句话描述该类的功能]
*
* @author : [xupeng]
* @version : [v1.0]
* @createTime : [2021/8/17 16:05]
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
public class JobDetail {
private Long id;
private String name;
private int age;
private String street;
}
4.编写config
ElasticSearchConfig:
package com.xupeng.es.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* [一句话描述该类的功能]
*
* @author : [xupeng]
* @version : [v1.0]
* @createTime : [2021/8/17 16:02]
*/
@Configuration
public class ElasticSearchConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestClientBuilder restClientBuilder = RestClient.builder(
//如果是集群这里有多个HttpHost
new HttpHost("192.168.210.149", 9200, "http")
);
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder);
return restHighLevelClient;
}
}
5.编写工具类和测试类
EsApplicationTests:
package com.xupeng.es;
import com.alibaba.fastjson.JSONObject;
import com.xupeng.es.entity.JobDetail;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest
class EsApplicationTests {
//索引库名字
private static final String JOB_IDX = "job_index";
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 新增
* @param jobDetail
* @throws IOException
*/
public void add(JobDetail jobDetail) throws IOException {
//1.构建IndexRequest对象,用来描述ES发起请求的数据
IndexRequest indexRequest = new IndexRequest(JOB_IDX);
//2.设置文档ID
indexRequest.id(jobDetail.getId().toString());
//3.将实体对象转化为JSON
String json = JSONObject.toJSONString(jobDetail);
//4.使用IndexRequest.source方法设置文档数据,并设置请求的数据为json格式
indexRequest.source(json, XContentType.JSON);
//5.使用restHighLevelClient调用index方法发起请求,将一个文档添加到索引中
restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
}
/**
* 根据ID查找
* @param id
* @return
* @throws IOException
*/
public JobDetail findById(long id) throws IOException {
//1.构建GetRequest
GetRequest getRequest = new GetRequest(JOB_IDX, id + "");
//2.使用restHighLevelClient.get发送GetRequest请求,并获取到es服务器的响应
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
//3.将es相应响应的数据转换为json字符串
String json = getResponse.getSourceAsString();
//4.将json转换为对象
JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
//5.记得,单独设置ID
jobDetail.setId(id);
return jobDetail;
}
/**
* 更新
* @param jobDetail
* @throws IOException
*/
public void update(JobDetail jobDetail) throws IOException {
GetRequest getRequest = new GetRequest(JOB_IDX, jobDetail.getId().toString());
boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
if (exists) {
UpdateRequest updateRequest = new UpdateRequest(JOB_IDX, jobDetail.getId().toString());
updateRequest.doc(JSONObject.toJSONString(jobDetail), XContentType.JSON);
restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
}
}
/**
* 删除
* @param id
* @throws IOException
*/
public void deleteById(long id) throws IOException {
DeleteRequest deleteRequest = new DeleteRequest(JOB_IDX, id + "");
restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
}
public List<JobDetail> searchByKeywords(String keywords) throws IOException {
//1.构建SearchRequest检索请求
SearchRequest searchRequest = new SearchRequest(JOB_IDX);
//2.创建SearchSourceBuilder专门用于构建查询条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//3.构建一个查询条件,并配置到SearchSourceBuilder
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keywords, "name","street");
searchSourceBuilder.query(multiMatchQueryBuilder);
//4.调用searchRequest.source将查询条件设置到检所请求
searchRequest.source(searchSourceBuilder);
//5.执行restHighLevelClient.search发起请求
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hitArray = searchResponse.getHits().getHits();
//6.遍历结果
ArrayList<JobDetail> jobDetailArrayList = new ArrayList<JobDetail>();
for (SearchHit documentFields : hitArray) {
String json = documentFields.getSourceAsString();
JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
jobDetail.setId(Long.parseLong(documentFields.getId()));
jobDetailArrayList.add(jobDetail);
}
return jobDetailArrayList;
}
public Map<String, Object> searchByPage(String keywords, int pageNum, int pageSize) throws IOException {
//1.构建SearchRequest检索请求
SearchRequest searchRequest = new SearchRequest(JOB_IDX);
//2.创建SearchSourceBuilder专门用于构建查询条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//3.构建一个查询条件,并配置到SearchSourceBuilder
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keywords, "name", "street");
searchSourceBuilder.query(multiMatchQueryBuilder);
//用于分页
searchSourceBuilder.size(pageSize);
searchSourceBuilder.from((pageNum - 1) * pageSize);
//4.调用searchRequest.source将查询条件设置到检所请求
searchRequest.source(searchSourceBuilder);
//5.执行restHighLevelClient.search发起请求
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hitArray = searchResponse.getHits().getHits();
//6.遍历结果
ArrayList<JobDetail> jobDetailArrayList = new ArrayList<JobDetail>();
for (SearchHit documentFields : hitArray) {
String json = documentFields.getSourceAsString();
JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
jobDetail.setId(Long.parseLong(documentFields.getId()));
jobDetailArrayList.add(jobDetail);
}
//结果封装到map中
long totalNum = searchResponse.getHits().getTotalHits().value;
HashMap map = new HashMap();
map.put("total", totalNum);
map.put("content", jobDetailArrayList);
return map;
}
public Map<String, Object> searchByLhPage(String keywords, String scrollId, int pageSize) throws IOException {
SearchResponse searchResponse = null;
//1.构建SearchRequest检索请求
SearchRequest searchRequest = new SearchRequest(JOB_IDX);
//2.创建SearchSourceBuilder专门用于构建查询条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//3.构建一个查询条件,并配置到SearchSourceBuilder
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keywords, "name", "street");
searchSourceBuilder.query(multiMatchQueryBuilder);
//设置高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
highlightBuilder.field("street");
highlightBuilder.preTags("<font color='red'>");
highlightBuilder.postTags("</font>");
//给请求设置高亮
searchSourceBuilder.highlighter(highlightBuilder);
//用于分页
searchSourceBuilder.size(pageSize);
//4.调用searchRequest.source将查询条件设置到检所请求
searchRequest.source(searchSourceBuilder);
//5.执行restHighLevelClient.search发起请求
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hitArray = searchResponse.getHits().getHits();
//6.遍历结果
ArrayList<JobDetail> jobDetailArrayList = new ArrayList<JobDetail>();
for (SearchHit documentFields : hitArray) {
String json = documentFields.getSourceAsString();
JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
jobDetail.setId(Long.parseLong(documentFields.getId()));
jobDetailArrayList.add(jobDetail);
//设置高亮的一些文本到实体类中
Map<String, HighlightField> highlightFieldMap = documentFields.getHighlightFields();
HighlightField nameHL = highlightFieldMap.get("name");
HighlightField streetHl = highlightFieldMap.get("street");
if (nameHL != null) {
Text[] fragments = nameHL.getFragments();
StringBuilder builder = new StringBuilder();
for (Text text : fragments) {
builder.append(text);
}
jobDetail.setName(builder.toString());
}
if (streetHl != null) {
Text[] fragments = streetHl.getFragments();
StringBuilder builder = new StringBuilder();
for (Text text : fragments) {
builder.append(text);
}
jobDetail.setStreet(builder.toString());
}
}
//结果封装到map中
long totalNum = searchResponse.getHits().getTotalHits().value;
HashMap map = new HashMap();
map.put("total", totalNum);
map.put("content", jobDetailArrayList);
return map;
}
public void close() throws IOException {
restHighLevelClient.close();
}
//-------------------------------------------------------------------------------------
//上述方法测试
@Test
public void doAdd() throws IOException {
JobDetail jobDetail = new JobDetail();
jobDetail.setId(22L);
jobDetail.setName("2b2");
jobDetail.setAge(22);
jobDetail.setStreet("22");
add(jobDetail);
}
@Test
public void doFindById() throws IOException {
System.out.println(findById(11));
}
@Test
public void doUpdate() throws IOException {
JobDetail jobDetail = findById(11);
jobDetail.setName("bbb");
update(jobDetail);
System.out.println(findById(11));
}
@Test
public void doSearch() throws IOException {
List<JobDetail> jobDetailList = searchByKeywords("bbb");
for(JobDetail jobDetail:jobDetailList){
System.out.println(jobDetail);
}
}
@Test
public void doSearchHL() throws IOException {
Map<String,Object> map = searchByLhPage("bbb","",10);
System.out.println(map);
}
}
二、模拟京东的后端实现
1.我们先来给es建表
常规字段 + 属性字段,其中属性字段为数组
PUT product_db
{
"mappings": {
"properties": {
"id":{
"type": "long"
},
"name":{
"type": "text",
"analyzer": "ik_max_word"
},
"keywords":{
"type": "text",
"analyzer": "ik_max_word"
},
"subTitle":{
"type": "text",
"analyzer": "ik_max_word"
},
"putawayDate":{
"type": "date"
},
"price":{
"type": "double"
},
"promotionPrice":{
"type": "keyword"
},
"originalPrice":{
"type": "keyword"
},
"pic":{
"type": "keyword"
},
"sale":{
"type": "long"
},
"hasStock":{
"type": "boolean"
},
"brandId":{
"type": "long"
},
"brandName":{
"type": "keyword"
},
"brandImg":{
"type": "keyword"
},
"categoryId":{
"type": "long"
},
"categoryName":{
"type": "keyword"
},
"attrs":{
"type": "nested",
"properties": {
"attrId":{
"type":"long"
},
"attrName":{
"type":"keyword"
},
"attrValue":{
"type":"keyword"
}
}
}
}
}
}
2.设置数据
PUT /product_db/_doc/1
{
"id":"1",
"name":"小米11手机",
"keywords":"小米手机",
"subTitle":"小米智慧全面屏手机,双卡双待",
"putawayDate":"2021-04-01",
"price":"3999",
"promotionPrice":"2999",
"originalPrice":"5999",
"pic":"xiaomi.jpg",
"sale":999,
"hasStock":true,
"brandId":"1",
"brandName":"小米",
"brandImg":"xiaomibrand.jpg",
"categoryId":"1",
"categoryName":"手机通讯",
"attrs":[
{
"attrId":1,
"attrName":"cpu",
"attrValue":"2核"
},
{
"attrId":2,
"attrName":"颜色",
"attrValue":"黑色"
}
]
}
PUT /product_db/_doc/2
{
"id":"2",
"name":"苹果手机",
"keywords":"苹果手机",
"subTitle":"苹果5G手机",
"putawayDate":"2021-04-01",
"price":"4999",
"promotionPrice":"2999",
"originalPrice":"5999",
"pic":"pingguo.jpg",
"sale":999,
"hasStock":true,
"brandId":"1",
"brandName":"苹果",
"brandImg":"pingguobrand.jpg",
"categoryId":"1",
"categoryName":"手机通讯",
"attrs":[
{
"attrId":3,
"attrName":"外壳",
"attrValue":"塑料"
},
{
"attrId":2,
"attrName":"颜色",
"attrValue":"白色"
}
]
}
|