在工作当中用到了elasticsearch,需求上有个搜索功能,在这里总结了一下。
首先,SpringBoot对ES的支持jar包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
其次,安装完成ES后,在SpringBoot配置文件中配置ES的内容,这里配置的比较简单,可以从网上查找详细的配置,这里就不再一一讲述了。
# 开启 Elasticsearch 仓库(默认值:true)
spring.data.elasticsearch.repositories.enabled=true
#ES配置路径
spring.data.elasticsearch.cluster-nodes=192.168.8.122:9300
# 连接超时的时间
spring.data.elasticsearch.properties.transport.tcp.connect_timeout=120s
实体类(get、set...等这里就省略了):
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.io.Serializable;
@Document(indexName = "file", type = "fileData")
public class ESFileData implements Serializable {
@Id
private String id;
@Field(type = FieldType.Text)
private String projectId;
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String fileName;
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String data;
@Field(type = FieldType.Text)
private String time;
Service:
import com.ecostor.assets.model.ESFileData;
import java.util.List;
public interface FileDataService {
List<ESFileData> esFile(String string, int page, int size);
}
实现:
import com.ecostor.assets.model.ESFileData;
import com.ecostor.es.service.FileDataService;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class FileDataServiceImpl implements FileDataService {
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
@Override
public List<ESFileData> esFile(String string, int page, int size) {
List<ESFileData> list = new ArrayList<>();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
String sousuo = "";
if (string != null && string.trim() != "") {
sousuo = string.trim();
} else {
return list;
}
String[] words = sousuo.split("\\s+");
for (String word : words) {
boolQuery.should(QueryBuilders.wildcardQuery("fileName",word));
boolQuery.should(QueryBuilders.wildcardQuery("data", word));
}
boolQuery.minimumShouldMatch(1);
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withPageable(PageRequest.of(page, size))
.withHighlightFields(new HighlightBuilder.Field("*").requireFieldMatch(false).preTags("<span style='color:red'>").postTags("</span>"))
.withQuery(boolQuery)
.build();
SearchResultMapper searchResultMapper = new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
List<ESFileData> list = new ArrayList<>();
SearchHit[] hits = searchResponse.getHits().getHits();
for (SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
ESFileData esFileData = new ESFileData();
esFileData.setId(hit.getId());
esFileData.setProjectId(sourceAsMap.get("projectId").toString());
esFileData.setFileName(sourceAsMap.get("fileName").toString());
esFileData.setData(sourceAsMap.get("data").toString());
esFileData.setTime(sourceAsMap.get("time").toString());
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (highlightFields.containsKey("fileName")) {
esFileData.setFileName(highlightFields.get("fileName").fragments()[0].toString());
}
if (highlightFields.containsKey("data")) {
System.err.println(highlightFields.get("data").fragments()[0].toString());
esFileData.setData(highlightFields.get("data").fragments()[0].toString());
}
list.add(esFileData);
}
return new AggregatedPageImpl<T>((List<T>) list);
}
};
list = elasticsearchTemplate.queryForPage(searchQuery, ESFileData.class, searchResultMapper).getContent();
return list;
}
}
这里只写了一种简单的搜索模式,ES对搜索的支持有很多种,各种复杂搜索需要好好研究研究咯!