記,寫一個(gè)簡單的es分詞demo,es版本6.8.12
如果使用es7有些方法可能會(huì)有所改變,請參考7的文檔
es安裝教程:http://t.csdn.cn/BSh12
1. 創(chuàng)建ES實(shí)體
怎么簡單怎么來
@Data
@Document(indexName = "goods")
public class GoodsEsItem implements Serializable {
//主鍵
@Id
private Long id;
@Field(type = FieldType.Text, analyzer = "ik_max_word") //商品名
private String name;
private String category;
@Field(type = FieldType.Date)
private Date create_time;
@Field(type = FieldType.Date)
private Date update_time;
}
2. 創(chuàng)建查詢實(shí)體
@Data
public class GoodsQueryVo {
/**
* 關(guān)鍵字
*/
private String keyword;
/**
* 分類
*/
private String category;
/**
* 當(dāng)前頁
*/
private Integer current;
/**
* 每頁大小
*/
private Integer pageSize;
/**
* 排序字段
*/
private String sfield;
/**
* 排序格式asc,desc
*/
private String sm;
}
3. 查詢方法實(shí)現(xiàn)
3.1 核心代碼
@Override
public Map<String, Object> searchByKeyword(GoodsQueryVo goodsQueryVo) {
//構(gòu)建查詢條件
NativeSearchQueryBuilder queryBuilder = queryBuilder(goodsQueryVo);
//添加高亮域
HighlightBuilder.Field field = new HighlightBuilder.
Field("name"). //指定的高亮域
preTags("<span style=\"color:red\">"). //前綴
postTags("</span>"). //后綴
fragmentSize(100);
queryBuilder.withHighlightFields(field);
//執(zhí)行搜索。HighlightResultMapper處理高亮文本
AggregatedPage<PblGoodsEsItem> results = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), PblGoodsEsItem.class, new HighlightResultMapper());
//結(jié)果集
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("list", results.getContent());
resultMap.put("total", results.getTotalElements());
return resultMap;
}
3.2 構(gòu)建查詢條件
商品名稱加了 @Field(type = FieldType.Text, analyzer = “ik_max_word”) 會(huì)自動(dòng)分詞
private NativeSearchQueryBuilder queryBuilder(GoodsQueryVo goodsQueryVo) {
//關(guān)鍵字分詞
EsIkResult esIkResult = keywordToken(goodsQueryVo);
List<String> tokens = esIkResult.getTokens().stream().map(EsIkResult.token::getToken).collect(Collectors.toList());
//QueryBuilder構(gòu)建
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//多條件組合查詢對象
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//關(guān)鍵字條件should構(gòu)建or條件,must構(gòu)建and條件
BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
tokens.forEach(e -> {
keywordQuery.should(QueryBuilders.termQuery("name", e));
});
//分類條件
if (!StringUtils.isEmpty(goodsQueryVo.getCategory())) {
boolQuery.must(QueryBuilders.termQuery("category",goodsQueryVo.getCategory()));
}
//這里的關(guān)系為(keyword1 or keyword2) and category
boolQuery.must(keywordQuery);
//分頁
queryBuilder.withPageable(PageRequest.of(currentPage(goodsQueryVo), goodsQueryVo.getPageSize()));
//排序
String sfield = goodsQueryVo.getSfield();
String sm = goodsQueryVo.getSm();
if (!StringUtils.isEmpty(sfield) && !StringUtils.isEmpty(sm)) {
queryBuilder.withSort(
SortBuilders.fieldSort(sfield) //排序域
.order(SortOrder.valueOf(sm))); //排序方式
}
return queryBuilder.withQuery(boolQuery);
}
分頁處理
public int currentPage(GoodsQueryVo goodsQueryVo) {
try {
Object currentPage = goodsQueryVo.getCurrent();
return Integer.parseInt(currentPage.toString()) > 0 ? Integer.parseInt(currentPage.toString()) - 1 : 0;
} catch (Exception e) {
return 0;
}
}
3.2.1 關(guān)鍵詞分詞
當(dāng)輸入衣服鞋子的時(shí)候會(huì)將關(guān)鍵字分為衣服,鞋子去查詢
@Data
public class EsIkResult {
private List<token> tokens;
@Data
public static class token{
private String token;
@JSONField(name = "start_offset")
private Integer startOffset;
@JSONField(name = "end_offset")
private Integer endOffset;
private String type;
private Integer position;
}
}
HttpUtil是自己封裝的http請求類,可以根據(jù)自己的方式去發(fā)出請求文章來源地址http://www.zghlxwxcb.cn/news/detail-475419.html
private EsIkResult keywordToken(GoodsQueryVo goodsQueryVo) {
HashMap<String, Object> params = new HashMap<>();
params.put("analyzer", "ik_max_word");
params.put("text", goodsQueryVo.getKeyword());
return HttpUtil.post("http://localhost:9200/_analyze?pretty", params, EsIkResult.class);
}
3.3 高亮處理
高亮處理mapper,處理高亮數(shù)據(jù),復(fù)制用即可,不需要記
public class HighlightResultMapper extends DefaultResultMapper {
/***
* 處理結(jié)果集
*/
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
//所有數(shù)據(jù)
for (SearchHit hit : response.getHits()) {
//當(dāng)前單條數(shù)據(jù)
Map<String, Object> sourceMap = hit.getSourceAsMap();
//高亮數(shù)據(jù)
for (Map.Entry<String, HighlightField> entry : hit.getHighlightFields().entrySet()) {
String key = entry.getKey();
if (sourceMap.containsKey(key)) {
Text[] fragments = entry.getValue().getFragments();
sourceMap.put(key, transTextArrayToString(fragments));
}
}
hit.sourceRef(new ByteBufferReference(ByteBuffer.wrap(JSONObject.toJSONString(sourceMap).getBytes())));
}
return super.mapResults(response, clazz, pageable);
}
/***
* 拼接數(shù)據(jù)碎片
*/
private String transTextArrayToString(Text[] fragments) {
if (null == fragments) {
return "";
}
StringBuffer buffer = new StringBuffer();
for (Text fragment : fragments) {
buffer.append(fragment.string());
}
return buffer.toString();
}
}
添加高亮,在上面·searchByKeyword
方法有寫到
此處會(huì)將name字段含有關(guān)鍵字的文本替換成<span style=“color:red”> 包含,前端用html回顯即可
示例,搜索衣服
//添加高亮域
HighlightBuilder.Field field = new HighlightBuilder.
Field("name"). //指定的高亮域
preTags("<span style=\"color:red\">"). //前綴
postTags("</span>"). //后綴
fragmentSize(100);
queryBuilder.withHighlightFields(field);
//執(zhí)行搜索。HighlightResultMapper處理高亮文本
AggregatedPage<PblGoodsEsItem> results = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), PblGoodsEsItem.class, new HighlightResultMapper());
4.完整查詢代碼展示
ps:
高亮處理代碼上方已給出,此處只給出搜索代碼文章來源:http://www.zghlxwxcb.cn/news/detail-475419.html
HttpUtil是自己封裝的http請求類,可以根據(jù)自己的方式去發(fā)出請求
@Service
public class GoodsEsServiceImpl implements GoodsEsService {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Override
public Map<String, Object> searchByKeyword(GoodsQueryVo goodsQueryVo) {
//構(gòu)建查詢條件
NativeSearchQueryBuilder queryBuilder = queryBuilder(goodsQueryVo);
//添加高亮域
HighlightBuilder.Field field = new HighlightBuilder.
Field("name"). //指定的高亮域
preTags("<span style=\"color:red\">"). //前綴
postTags("</span>"). //后綴
fragmentSize(100);
queryBuilder.withHighlightFields(field);
//執(zhí)行搜索。HighlightResultMapper處理高亮文本
AggregatedPage<PblGoodsEsItem> results = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), PblGoodsEsItem.class, new HighlightResultMapper());
//結(jié)果集
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("list", results.getContent());
resultMap.put("total", results.getTotalElements());
return resultMap;
}
private NativeSearchQueryBuilder queryBuilder(GoodsQueryVo goodsQueryVo) {
//關(guān)鍵字分詞
EsIkResult esIkResult = keywordToken(goodsQueryVo);
List<String> tokens = esIkResult.getTokens().stream().map(EsIkResult.token::getToken).collect(Collectors.toList());
//QueryBuilder構(gòu)建
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
//多條件組合查詢對象
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//關(guān)鍵字條件should構(gòu)建or條件,must構(gòu)建and條件
BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
tokens.forEach(e -> {
keywordQuery.should(QueryBuilders.termQuery("name", e));
});
//分類條件
if (!StringUtils.isEmpty(goodsQueryVo.getCategory())) {
boolQuery.must(QueryBuilders.termQuery("category",goodsQueryVo.getCategory()));
}
//這里的關(guān)系為(keyword1 or keyword2) and category
boolQuery.must(keywordQuery);
//分頁
queryBuilder.withPageable(PageRequest.of(currentPage(goodsQueryVo), goodsQueryVo.getPageSize()));
//排序
String sfield = goodsQueryVo.getSfield();
String sm = goodsQueryVo.getSm();
if (!StringUtils.isEmpty(sfield) && !StringUtils.isEmpty(sm)) {
queryBuilder.withSort(
SortBuilders.fieldSort(sfield) //排序域
.order(SortOrder.valueOf(sm))); //排序方式
}
return queryBuilder.withQuery(boolQuery);
}
public int currentPage(GoodsQueryVo goodsQueryVo) {
try {
Object currentPage = goodsQueryVo.getCurrent();
return Integer.parseInt(currentPage.toString()) > 0 ? Integer.parseInt(currentPage.toString()) - 1 : 0;
} catch (Exception e) {
return 0;
}
}
private EsIkResult keywordToken(GoodsQueryVo goodsQueryVo) {
HashMap<String, Object> params = new HashMap<>();
params.put("analyzer", "ik_max_word");
params.put("text", goodsQueryVo.getKeyword());
return HttpUtil.post("http://localhost:9200/_analyze?pretty", params, EsIkResult.class);
}
}
到了這里,關(guān)于spring boot使用elasticsearch分詞,排序,分頁,高亮簡單示例的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!