注意:没有实现排序和分页
1 导入依赖包
<!-- springBoot 项目-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2 新建一个repository
继承ES这个接口
package com.lenovo.qes.portal.modules.knowledge.demo.repository;
import com.lenovo.qes.portal.modules.knowledge.demo.document.ProductDocument;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Component;
/**
* @author zhoudong
* @version 0.1
* @date 2018/12/13 17:35
*/
@Component
public interface ProductDocumentRepository extends ElasticsearchRepository<ProductDocument,String> {
}
3 使用repository
package com.lenovo.qes.portal.modules.knowledge.demo.service.impl;
import com.alibaba.fastjson.JSON;
import com.lenovo.qes.portal.modules.knowledge.demo.document.ProductDocument;
import com.lenovo.qes.portal.modules.knowledge.demo.repository.ProductDocumentRepository;
import com.lenovo.qes.portal.modules.knowledge.demo.service.EsSearchService;
import com.lenovo.qes.portal.modules.knowledge.service.impl.BaseSearchServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
/**
* elasticsearch 搜索引擎 service实现
* @author zhoudong
* @version 0.1
* @date 2018/12/13 15:33
*/
@Service
public class EsSearchServiceImpl extends BaseSearchServiceImpl<ProductDocument> implements EsSearchService {
private Logger log = LoggerFactory.getLogger(getClass());
@Resource
private ElasticsearchTemplate elasticsearchTemplate;
@Resource
private ProductDocumentRepository productDocumentRepository;
@Override
public void save(ProductDocument ... productDocuments) {
elasticsearchTemplate.putMapping(ProductDocument.class);
if(productDocuments.length > 0){
/**
* 批量保存
**/
productDocumentRepository.saveAll(Arrays.asList(productDocuments));
log.info("【保存索引】:{}",JSON.toJSONString());
}
}
@Override
public void delete(String id) {
/**
* 根据id删除
**/
productDocumentRepository.deleteById(id);
}
@Override
public void deleteAll() {
/**
* 删除所有
**/
productDocumentRepository.deleteAll();
}
@Override
public ProductDocument getById(String id) {
/**
* 根据id查询
**/
return productDocumentRepository.findById(id).get();
}
@Override
public List<ProductDocument> getAll() {
List<ProductDocument> list = new ArrayList<>();
/**
* 查询所有
**/
productDocumentRepository.findAll().forEach(list::add);
return list;
}
}
es中文档、java实体类应该如下映射:
package com.lenovo.qes.portal.modules.knowledge.demo.document;
import lombok.Data;
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.Mapping;
import java.io.Serializable;
import java.util.Date;
/**
* 产品实体
* @author zhoudong
* @version 0.1
* @date 2018/12/13 15:22
* @Mapping 解决IK分词不能使用问题
*/
@Data
@Document(indexName = "orders", type = "product")
@Mapping(mappingPath = "productIndex.json")
public class ProductDocument implements Serializable {
@Id
private String id;
@Field(analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
private String productName;
@Field(analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
private String productDesc;
private Date createTime;
private Date updateTime;
}
4 补充
由于全部代码非常多,此处只展示关键部分
/**
* elasticsearch 搜索引擎
* @author zhoudong
* @version 0.1
* @date 2018/12/13 15:33
*/
@Service
public class BaseSearchServiceImpl<T> implements BaseSearchService<T> {
private Logger log = LoggerFactory.getLogger(getClass());
@Resource
private ElasticsearchTemplate elasticsearchTemplate;
@Override
public List<T> query(String keyword, Class<T> clazz) {
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(new QueryStringQueryBuilder(keyword))
.withSort(SortBuilders.scoreSort().order(SortOrder.DESC))
// .withSort(new FieldSortBuilder("createTime").order(SortOrder.DESC))
.build();
return elasticsearchTemplate.queryForList(searchQuery,clazz);
}
/**
* 高亮显示
* @auther: zhoudong
* @date: 2018/12/13 21:22
*/
@Override
public List<Map<String,Object>> queryHit(String keyword,String indexName,String ... fieldNames) {
// 构造查询条件,使用标准分词器.
QueryBuilder matchQuery = createQueryBuilder(keyword,fieldNames);
// 设置高亮,使用默认的highlighter高亮器
HighlightBuilder highlightBuilder = createHighlightBuilder(fieldNames);
// 设置查询字段
SearchResponse response = elasticsearchTemplate.getClient().prepareSearch(indexName)
.setQuery(matchQuery)
.highlighter(highlightBuilder)
.setSize(10000) // 设置一次返回的文档数量,最大值:10000
.get();
// 返回搜索结果
SearchHits hits = response.getHits();
return getHitList(hits);
}
/**
* 高亮显示,返回分页
* @auther: zhoudong
* @date: 2018/12/18 10:29
*/
@Override
public Page<Map<String, Object>> queryHitByPage(int pageNo,int pageSize, String keyword, String indexName, String... fieldNames) {
// 构造查询条件,使用标准分词器.
QueryBuilder matchQuery = createQueryBuilder(keyword,fieldNames);
// 设置高亮,使用默认的highlighter高亮器
HighlightBuilder highlightBuilder = createHighlightBuilder(fieldNames);
// 设置查询字段
SearchResponse response = elasticsearchTemplate.getClient().prepareSearch(indexName)
.setQuery(matchQuery)
.highlighter(highlightBuilder)
.setFrom((pageNo-1) * pageSize)
.setSize(pageNo * pageSize) // 设置一次返回的文档数量,最大值:10000
.get();
// 返回搜索结果
SearchHits hits = response.getHits();
Long totalCount = hits.getTotalHits();
Page<Map<String, Object>> page = new Page<>(pageNo,pageSize,totalCount.intValue());
page.setList(getHitList(hits));
return page;
}
/**
* 构造查询条件
* @auther: zhoudong
* @date: 2018/12/18 10:42
*/
private QueryBuilder createQueryBuilder(String keyword, String... fieldNames){
// 构造查询条件,使用标准分词器.
return QueryBuilders.multiMatchQuery(keyword,fieldNames) // matchQuery(),单字段搜索
.analyzer("ik_max_word")
.operator(Operator.OR);
}
/**
* 构造高亮器
* @auther: zhoudong
* @date: 2018/12/18 10:44
*/
private HighlightBuilder createHighlightBuilder(String... fieldNames){
// 设置高亮,使用默认的highlighter高亮器
HighlightBuilder highlightBuilder = new HighlightBuilder()
// .field("productName")
.preTags("<span style='color:red'>")
.postTags("</span>");
// 设置高亮字段
for (String fieldName: fieldNames) highlightBuilder.field(fieldName);
return highlightBuilder;
}
/**
* 处理高亮结果
* @auther: zhoudong
* @date: 2018/12/18 10:48
*/
private List<Map<String,Object>> getHitList(SearchHits hits){
List<Map<String,Object>> list = new ArrayList<>();
Map<String,Object> map;
for(SearchHit searchHit : hits){
map = new HashMap<>();
// 处理源数据
map.put("source",searchHit.getSourceAsMap());
// 处理高亮数据
Map<String,Object> hitMap = new HashMap<>();
searchHit.getHighlightFields().forEach((k,v) -> {
String hight = "";
for(Text text : v.getFragments()) hight += text.string();
hitMap.put(v.getName(),hight);
});
map.put("highlight",hitMap);
list.add(map);
}
return list;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteIndex(String indexName) {
elasticsearchTemplate.deleteIndex(indexName);
}
}
public interface EsSearchService extends BaseSearchService<ProductDocument> {
/**
* 保存
* @auther: zhoudong
* @date: 2018/12/13 16:02
*/
void save(ProductDocument... productDocuments);
/**
* 删除
* @param id
*/
void delete(String id);
/**
* 清空索引
*/
void deleteAll();
/**
* 根据ID查询
* @param id
* @return
*/
ProductDocument getById(String id);
/**
* 查询全部
* @return
*/
List<ProductDocument> getAll();
}
public interface BaseSearchService<T> {
/**
* 搜 索
* @param keyword
* @param clazz
* @return
*/
List<T> query(String keyword, Class<T> clazz);
/**
* 搜索高亮显示
* @param keyword 关键字
* @param indexName 索引库
* @param fieldNames 搜索的字段
* @return
*/
List<Map<String,Object>> queryHit(String keyword, String indexName, String ... fieldNames);
/**
* 搜索高亮显示,返回分页
* @param pageNo 当前页
* @param pageSize 每页显示的总条数
* @param keyword 关键字
* @param indexName 索引库
* @param fieldNames 搜索的字段
* @return
*/
Page<Map<String,Object>> queryHitByPage(int pageNo,int pageSize,String keyword, String indexName, String ... fieldNames);
/**
* 删除索引库
* @param indexName
* @return
*/
void deleteIndex(String indexName);
}