需求:实现关键字查询,关键字查询可以输入多个,且以空格分开,然后查询条件高亮
一、mapping:
PUT /cartoonindex/
{
"mappings" : {
"cartoon" : {
"properties" : {
"name" : {
"type" : "text",
"analyzer" : "ik_max_word",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"introduction" : {
"type" : "text",
"analyzer" : "ik_max_word",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"time":{
"type" : "date"
}
}
}
}
}
二、插入数据
PUT cartoonindex/cartoon/1
{
"name":"火影忍者",
"introduction":"《火影忍者》是日本漫画家岸本齐史的代表作,作品于1999年开始在《周刊少年JUMP》上连载,于2014年11月10日发售的JUMP第50号完结;后日谈性质的外传漫画《火影忍者外传:第七代火影与绯色花月》则于同杂志2015年第22、23合并号开始短期连载,至同年第32号完结。故事成功地将原本隐藏在黑暗中,用世界上最强大的毅力和最艰辛的努力去做最密不可宣和隐讳残酷的事情的忍者,描绘成了太阳下最值得骄傲最光明无限的职业。在岸本齐史笔下的忍者世界中,每一位年轻的忍者都在开拓着属于自己的忍道。",
"time":"1999-10-01"
}
PUT cartoonindex/cartoon/2
{
"name":"龙珠",
"introduction":"《龙珠》(日文:ドラゴンボール、英文:DRAGON BALL)是东映动画制作的“龙珠系列”第一部动画TV,改编于著名漫画家·鸟山明的同名作品(1-194篇) [1] 。该作于1986年2月26日——1989年4月19日在富士电视台放送,共153话。主要讲述了孙悟空及伙伴们为了寻找能够实现愿望的七颗龙珠,从而踏上冒险的旅途,并在途中以变得更强为信仰勇往直前,突破自我的励志故事",
"time":"1986-02-24"
}
PUT cartoonindex/cartoon/3
{
"name":"海贼王",
"introduction":"《航海王》是日本漫画家尾田荣一郎作画的少年漫画作品,在《周刊少年Jump》1997年第34号开始连载。改编的电视动画《航海王》于1999年10月20日起在富士电视台首播。2012年5月11日,《航海王》获得第41回日本漫画家协会赏 [1] 。截至2015年6月15日,《航海王》以日本本土累计发行了3亿2086万6000本,被吉尼斯世界纪录官方认证为“世界上发行量最高的单一作者创作的系列漫画” [2] 。2017年7月21日,日本纪念日协会通过认证,将每年的7月22日设立为“ONE PIECE纪念日",
"time":"1999-12-05"
}
PUT cartoonindex/cartoon/4
{
"name":"银魂",
"introduction":"银魂》是由日本漫画家空知英秋创作的少年漫画作品,于2004年2号的《周刊少年Jump》开始连载,并于2018年42号结束连载。后转移至《JUMP GIGA》2019 WINTER vol.1~vol.3继续连载,而后转移到银魂App连载,并于2019年6月20日推送最终回。2006年4月4日起,由日升动画改编的同名电视动画开始在东京电视台放送。截至2018年8月,《银魂》日本国内单行本累计发行量突破5500万册。",
"time":"2006-05-06"
}
PUT cartoonindex/cartoon/5
{
"name":"一拳超人",
"introduction":"《一拳超人》是ONE原作,村田雄介作画,连载于网络漫画杂志《邻座的Young jump》上的漫画。 [1-2] 原为ONE在个人网站上连载的练笔之作, [3] 后被喜爱该作的另一漫画家村田雄介在征得ONE同意后重新绘制而成。电子版由哔哩哔哩漫画发布、漫番漫画同步日本连载发布。 [4] 截至2016年11月27日,重制版日文单行销量累计突破1111万部",
"time":"2009-09-30"
}
PUT cartoonindex/cartoon/6
{
"name":"进击的巨人",
"introduction":"《进击的巨人》(进撃の巨人),是日本漫画家谏山创创作的少年漫画作品,于2009年在讲谈社旗下的漫画杂志《别册少年Magazine》上开始连载。该作品曾获2011年“这本漫画真厉害!”男性榜第1名、“讲谈社漫画赏少年部门赏”等奖项。2012年12月正式宣布TV动画化,2013年4月6日,由WITSTUDIO改编的同名电视动画正式开始放送。截止至2017年3月,单行本21卷累计发行量突破6300万册。卷均300万册",
"time":"2013-04-16"
}
三、es查询语句
GET /cartoonindex/_search/
{
"query": {
"bool": {
"must":[{
"multi_match":{
"query":"少年",
"fields":["name","introduction"],
"type":"phrase",
"operator":"or"
}
},
{
"multi_match":{
"query":"火影",
"fields":["name","introduction"],
"type":"phrase",
"operator":"or"
}
},
{
"range": {
"time": {
"gte": "1900-01-01",
"lte": "2000-01-01"
}
}
}
]
}
},
"highlight": {
"fields": {
"name": {},
"introduction": {}
},
"pre_tags": ["<em class='hight'>"],
"post_tags": [
"</em>"
]
}
, "sort": [
{
"time": {
"order": "desc"
}
}
]
}
关键字查询为:火影 少年 两个条件,可以看到满足的结果有一个,且查询条件有高亮标签
四、springboot整合:
1、pom文件:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--es依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
2、返回对象:
@Document(indexName = "cartoonindex",type = "cartoon")
@Data
public class Carton {
@Id
private String id;
private String name;
private String introduction;
private String time;
}
3、查询代码:
package com.windy.springbootes.controller;
import com.windy.springbootes.entity.Carton;
import com.windy.springbootes.entity.Company;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
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.Page;
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.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
/**
* @author: windy
* @create: 2020-01-04 11:32
*/
@Controller
@Slf4j
public class CartonController {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
/**
* 高亮,分页查询,排序,多关键字查询
*/
@ResponseBody
@RequestMapping("/searchCarton")
public Page<Carton> searchNew(String keyWord, @PageableDefault(page = 0, value = 3) Pageable pageable) {
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
if (!StringUtils.isEmpty(keyWord)) {
String[] words = keyWord.trim().split("\\s+");
for(String word : words){
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(word, new String[]{"name", "introduction"});
multiMatchQueryBuilder.type("phrase");
multiMatchQueryBuilder.operator();
multiMatchQueryBuilder.slop();
boolQuery.must(multiMatchQueryBuilder);
}
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
highlightBuilder.field("introduction");
highlightBuilder.preTags("<em class='hight'>");
highlightBuilder.postTags("</em>");
SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable).withHighlightBuilder(highlightBuilder)
.withQuery(boolQuery).build();
log.info("query---{}",searchQuery.getQuery());
return elasticsearchTemplate.queryForPage(searchQuery, Carton.class, new SearchResultMapper() {
@Override
public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
return null;
}
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
List<Carton> cartons = new ArrayList<>();
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
if (hits.getHits().length <= 0) {
return null;
}
Carton carton = new Carton();
carton.setId(hit.getId());
carton.setName(hit.getSourceAsMap().get("name").toString());
carton.setIntroduction(hit.getSourceAsMap().get("introduction").toString());
carton.setTime(hit.getSourceAsMap().get("time").toString());
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (highlightFields.containsKey("name")) {
carton.setName(highlightFields.get("name").getFragments()[0].toString());
}
if (highlightFields.containsKey("introduction")) {
carton.setIntroduction(highlightFields.get("introduction").getFragments()[0].toString());
}
cartons.add(carton);
}
return new AggregatedPageImpl<T>((List<T>) cartons, pageable, hits.getTotalHits(), hits.getMaxScore());
}
});
}else{
//如果没有关键字,则查询所有
SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable).withQuery(matchAllQuery()).build();
log.info("query---{}",searchQuery.getQuery());
List<Carton> cartons = elasticsearchTemplate.queryForList(searchQuery, Carton.class);
long count = elasticsearchTemplate.count(searchQuery);
return new AggregatedPageImpl<>(cartons, pageable, count, 0);
}
}
}
4、postman测试: