一、配置pom
pom.xml
<?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.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.li</groupId>
<artifactId>li-es-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>li-es-api</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<repackage.classifier/>
<spring-native.version>0.10.1</spring-native.version>
<!--更改默认es版本-->
<elasticsearch.version>7.8.0</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
<version>${spring-native.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<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>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
<classifier>${repackage.classifier}</classifier>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
</env>
</image>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<version>${spring-native.version}</version>
<executions>
<execution>
<id>test-generate</id>
<goals>
<goal>test-generate</goal>
</goals>
</execution>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<profiles>
<profile>
<id>native</id>
<properties>
<repackage.classifier>exec</repackage.classifier>
<native-buildtools.version>0.9.1</native-buildtools.version>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</profile>
</profiles>
</project>
二、编写配置文件
ElasticSearchConfig.java
@Configuration
public class ElasticSearchConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
//new HttpHost("localhost", 9201, "http")));
return client;
}
static BulkProcessor getProcessor(){
BiConsumer<BulkRequest, ActionListener<BulkResponse>> client = null;
return BulkProcessor.builder(client, new BulkProcessor.Listener() {
@Override
public void beforeBulk(long l, BulkRequest bulkRequest) {
}
@Override
public void afterBulk(long l, BulkRequest bulkRequest, BulkResponse bulkResponse) {
}
@Override
public void afterBulk(long l, BulkRequest bulkRequest, Throwable throwable) {
}
})//设置提交批处理操作的请求阀值数
.setBulkActions(20000)
//设置提交批处理操作的操作的请求大小阀值
.setBulkSize(new ByteSizeValue(500, ByteSizeUnit.MB))
// 设置刷新索引时间间隔
.setFlushInterval(TimeValue.timeValueSeconds(30))
//设置并发处理的线程个数
.setConcurrentRequests(30)
//设置回滚策略,等待时间1000ms,retry次数1次
.setBackoffPolicy(BackoffPolicy.exponentialBackoff(
TimeValue.timeValueMillis(1000), 1))
.build();
}
}
三、编写测试函数
test.java
@SpringBootTest
class LiEsApiApplicationTests {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
@Autowired
MmsMemberCompanyService mmsMemberCompanyService;
@Autowired
AssociationinfoService associationinfoService;
/*或者
*@Autowired
*private RestHighLevelClient restHighLevelClient;
* */
//索引创建
@Test
void testCreateIndex() throws IOException {
//1 创建索引
CreateIndexRequest request = new CreateIndexRequest("li_index");
//2 客户端执行请求 IndicesClient 获得响应
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(response);
}
//索引获取
@Test
void testGetIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("li_index");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
//索引删除
@Test
void testDelIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("li_index");
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
//添加文档
@Test
void testAddDoc() throws IOException {
User user = new User("li", 23);
IndexRequest request = new IndexRequest("li_index");
//规则 PUT /li_index/_doc/1
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));//request.timeout("1s");
//数据放入请求
IndexRequest source = request.source(JSON.toJSONString(user), XContentType.JSON);
//客户端发送请求
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
System.out.println(indexResponse.toString());
System.out.println(indexResponse.status());
}
//获取文档 GET /index/_doc/1
@Test
void testIsExistDoc() throws IOException {
GetRequest request = new GetRequest("li_index", "1");
//不获取返回的_source的上下文
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("");
boolean exists = client.exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
//获取文档信息
@Test
void testGetDoc() throws IOException {
GetRequest request = new GetRequest("li_index", "1");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString());
System.out.println(response);//和命令式 返回内容一样
}
//更新文档信息
@Test
void testUpdateDoc() throws IOException {
UpdateRequest request = new UpdateRequest("li_index", "1");
request.timeout("1s");
User user = new User("张三", 56);
UpdateRequest doc = request.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse updateResponse = client.update(doc, RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
System.out.println(updateResponse);//和命令式 返回内容一样
}
//删除文档记录
@Test
void testDelDoc() throws IOException {
DeleteRequest request = new DeleteRequest("li_index", "1");
request.timeout("1s");
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
//批量插入
@Test
void testBulkAddDoc() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
ArrayList<User> users = new ArrayList<>();
users.add(new User("java", 15));
users.add(new User("C", 16));
users.add(new User("C++", 17));
users.add(new User("python", 18));
users.add(new User("js", 19));
users.add(new User("es", 25));
users.add(new User("SSm", 35));
users.add(new User("cloud", 45));
for (int i = 0; i < users.size(); i++) {
bulkRequest.add(new IndexRequest("li_index")
.source(JSON.toJSONString(users.get(i)), XContentType.JSON)
);
}
BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulk.hasFailures());
}
//查询
// SearchRequest搜索请求
// SearchSourceBuilder条件构造
// HighLightBuilder构建高亮
//TermQueryBuilder精确查询
// /MatchALLQueryBuilder
//xxx QueryBuilder对应命令
//查询
@Test
void testSearch() throws IOException {
SearchRequest request = new SearchRequest(ESconst.ES_INDEX);
//构建搜索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//QueryBuilder queryBuilder = new QueryBuilder(); 不推荐
//QueryBuilders 工具类永远的神
TermQueryBuilder builder = QueryBuilders.termQuery("name", "java");
searchSourceBuilder.query(builder);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
request.source(searchSourceBuilder);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(search.getHits()));
System.out.println("===============");
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
//批量插入
@Test
void testBulkAddDocTest2() throws IOException {
int itemCount;
int doCount = 1;
do {
List<MmsMemberCompany> mmsMemberCompanies = mmsMemberCompanyService.selectAll();
itemCount = mmsMemberCompanies.size();
if (itemCount > 0) {
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
for (int i = 0; i < mmsMemberCompanies.size(); i++) {
MmsMemberCompany mmsMemberCompany = mmsMemberCompanies.get(i);
bulkRequest.add(new IndexRequest("mmsmembercompany_index")
.source(JSON.toJSONString(mmsMemberCompany), XContentType.JSON)
.id(mmsMemberCompany.getId())
);
System.out.println("===================" + "i=" + i);
}
System.out.println("执行次数:" + doCount);
doCount++;
BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulk.hasFailures());
Associationinfo associationinfo = new Associationinfo("test", mmsMemberCompanies.get(itemCount - 1).getUpdateTime(), 1);
associationinfoService.updateInfo(associationinfo);
}
} while (itemCount == 3000);
}
四、项目运用
4.1 编写pojo类
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ESCompanyListReq extends StartPage {
@NotNull
String name;
Long legalEntityId;
String creditCode;
Long id;
}
4.2 编写service类
@Service
public interface CompanySearchService {
/**
* @Description:模糊搜索-结果分页-内容高亮显示-按公司名字
* @Author: lya
* @Date: 2021/7/22 14:53
* @Param:ESCompany
* @Return:ESCompany
*/
public List<ESCompanyListReq> searchCompanyPageHighLight(ESCompanyListReq param) throws IOException;
}
@Slf4j
@Service
public class CompanySearchServiceImpl implements CompanySearchService {
@Resource
private RestHighLevelClient restHighLevelClient;
@Override
//模糊搜索company-结果分页-内容高亮显示
public List<ESCompanyListReq> searchCompanyPageHighLight(ESCompanyListReq param) throws IOException {
SearchRequest searchRequest = new SearchRequest(ES_INDEX_company);
//ES_INDEX_company 为静态常量自己配置即可,对应索引名称
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//分页
searchSourceBuilder.from(param.getPageIndex());
searchSourceBuilder.size(param.getPageSize());
//模糊匹配
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", param.getName());
searchSourceBuilder.query(matchQueryBuilder);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
highlightBuilder.requireFieldMatch(true);
highlightBuilder.preTags("<span style= 'color: red'>");
highlightBuilder.postTags("</span>");
searchSourceBuilder.highlighter(highlightBuilder);
//执行搜索
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//解析结果
ArrayList<Map<String, Object>> list = new ArrayList<>();
for (SearchHit hit : search.getHits().getHits()) {
//解析高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField name = highlightFields.get("name");
Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
//原来的字段换成现在的高亮字段
if (name != null) {
Text[] fragments = name.fragments();
String replace = "";
for (Text fragment : fragments) {
replace += fragment;
}
sourceAsMap.put("name", replace);
}
list.add(sourceAsMap);
}
ArrayList<ESCompanyListReq> esCompanies = new ArrayList<>();
for (Map<String, Object> map : list) {
String s = JSON.toJSONString(map);//-->Map集合转换成JSON字符串
ESCompanyListReq esCompany = JSON.parseObject(s, ESCompanyListReq.class);//将JSON字符串转换成实体类
esCompanies.add(esCompany);
}
return esCompanies;
}
}
4.3 编写controller类
@Slf4j
@RestController
@RequestMapping("/search")
public class IndexSearchController {
@Resource
CompanySearchService companySearchService;
@PostMapping("/listCompanyByCompanyName")
public Result CompanySearch(@Validated @RequestBody ESCompanyListReq req) throws IOException {
List<ESCompanyListReq> esCompanies = companySearchService.searchCompanyPageHighLight(req);
return Result.success(esCompanies);
}
}