SpringBoot + Elasticsearch7.6 實現簡單查詢及高亮分詞查詢

語言: CN / TW / HK

點選上方 匠心零度 ,選擇“ 設為星標

做積極的人,而不是積極廢人

來源 | blog.csdn.net/weixin_44102992/article/details/108033164/

01、前言

該文章需要提前準備好Elasticsearch7.6以及ik分詞器的環境,如果還沒準備好的可以看看之前以及發過的文章,liunx下安裝elasticsearch7.6、ik分詞器以及kibana視覺化工具 :https://blog.csdn.net/weixin_44102992/article/details/107954129

02、整合環境準備

1.匯入spring-data-elasticsearch依賴版本需要與Elasticsearch一致,還需要注意自己的springboot版本是否支援 本文springboot為2.3,依賴也為2.3,elasticsearch,為7.6.2

<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>${version}.RELEASE</version>
</dependency>

2.elasticsearch配置檔案

因為原來的配置不支援了 配置檔案如下:

@Configuration
public class EsConf {
@Value("${elasticSearch.url}")
private String edUrl;

//localhost:9200 寫在配置檔案中就可以了
@Bean
RestHighLevelClient client() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo(edUrl)//elasticsearch地址
.build();

return RestClients.create(clientConfiguration).rest();
}
}

3.實體類準備關於實體類中的幾個註解,不清楚的可以去檢視文件,這裡不過多介紹了

@Data
@Document(indexName = "user")//索引名稱 建議與實體類一致
public class User {
@Id
private Integer id;
@Field(type = FieldType.Auto)//自動檢測型別
private Integer age;
@Field(type = FieldType.Keyword)//手動設定為keyword 但同時也就不能分詞
private String name;
@Field(type = FieldType.Text,analyzer = "ik_smart",searchAnalyzer = "ik_max_word")//設定為text 可以分詞
private String info;
}

4.Elasticsearch Service準備 ElasticsearchRepository<,> 第一個就是所準備的實體類,第二個是id的型別 繼承完這個會提供最基本的增刪改查方法,也可以自己定義一些,自己定義的方法命名需要符合規則,並不需要自己去實現

public interface EsUserService extends ElasticsearchRepository<User,Integer> {
//根據name查詢
List<User> findByName(String name);

//根據name和info查詢
List<User> findByNameAndInfo(String name,String info);
}

03、簡單查詢

這裡直接使用假資料並沒有連線資料庫,還需要注意幾個點:1.elasticsearchTemplate需要採用ElasticsearchRestTemplate 原來的已經過時了 2.elasticsearch的mapping沒有自動生成,這導致了我們在實體類中指定的分詞器沒有生效,所以我在匯入資料的同時,手動匯入了mapping 3.LogAnnotation是我自定義的註解,大家可以直接去掉

controller如下:

@RestController
public class EsController {
@Autowired
private ElasticsearchRestTemplate elasticsearchTemplate;
@Autowired
private EsUserService esUserService;

private String[] names={"諸葛亮","曹操","李白","韓信","趙雲","小喬","狄仁傑","李四","諸小明","王五"};
private String[] infos={"我來自中國的一個小鄉村,地處湖南省","我來自中國的一個大城市,名叫上海,人們稱作魔都"
,"我來自東北,家住大囤裡,一口大碴子話"};
@LogAnnotation(requestRemark = "存資料")
@GetMapping("saveUser")
public ResultVO saveUser(){
//新增索引mapping 索引會自動建立但mapping自只用預設的這會導致分詞器不生效 所以這裡我們手動匯入mapping
elasticsearchTemplate.putMapping(User.class);
Random random = new Random();
List<User> users = new ArrayList<>();
for (int i=0;i<20;i++){
User user = new User();
user.setId(i);
user.setName(names[random.nextInt(9)]);
user.setAge(random.nextInt(40)+i);
user.setInfo(infos[random.nextInt(2)]);
users.add(user);
}
Iterable<User> users1 = esUserService.saveAll(users);
return new ResultVO(users1);
}

@LogAnnotation(requestRemark = "根據id查詢資料")
@GetMapping("getDataById")
public ResultVO getDataById(Integer id){
return new ResultVO(esUserService.findById(id));
}

@LogAnnotation(requestRemark = "分頁查詢所有資料")
@GetMapping("getAllDataByPage")
public ResultVO getAllDataByPage(){
//本該傳入page和size,這裡為了方便就直接寫死了
Pageable page = PageRequest.of(0,10, Sort.Direction.ASC,"id");
Page<User> all = esUserService.findAll(page);
return new ResultVO(all.getContent());
}

@LogAnnotation(requestRemark = "根據名字查詢")
@GetMapping("getDataByName")
public ResultVO getDataByName(String name){
return new ResultVO(esUserService.findByName(name));
}

@LogAnnotation(requestRemark = "根據名字和介紹查詢")
@GetMapping("getDataByNameAndInfo")
public ResultVO getDataByNameAndInfo(String name,String info){
//這裡是查詢兩個欄位取交集,即代表兩個條件需要同時滿足
return new ResultVO(esUserService.findByNameAndInfo(name,info));
}
}

測試結果:

04、分詞高亮查詢

    @LogAnnotation(requestRemark = "查詢高亮顯示")
@GetMapping("getHightByUser")
public ResultVO getHightByUser(String value){
//根據一個值查詢多個欄位 並高亮顯示 這裡的查詢是取並集,即多個欄位只需要有一個欄位滿足即可
//需要查詢的欄位
BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("info",value))
.should(QueryBuilders.matchQuery("name",value));
//構建高亮查詢
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQueryBuilder)
.withHighlightFields(
new HighlightBuilder.Field("info")
,new HighlightBuilder.Field("name"))
.withHighlightBuilder(new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>"))
.build();
//查詢
SearchHits<User> search = elasticsearchTemplate.search(searchQuery, User.class);
//得到查詢返回的內容
List<SearchHit<User>> searchHits = search.getSearchHits();
//設定一個最後需要返回的實體類集合
List<User> users = new ArrayList<>();
//遍歷返回的內容進行處理
for(SearchHit<User> searchHit:searchHits){
//高亮的內容
Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
//將高亮的內容填充到content中
searchHit.getContent().setName(highlightFields.get("name")==null ? searchHit.getContent().getName():highlightFields.get("name").get(0));
searchHit.getContent().setInfo(highlightFields.get("info")==null ? searchHit.getContent().getInfo():highlightFields.get("info").get(0));
//放到實體類中
users.add(searchHit.getContent());
}
return new ResultVO(users);
}

測試結果:

END

如果讀完覺得有收穫的話,歡迎點【好看】,關注【匠心零度】,查閱更多精彩歷史!!!

讓我“ 好看 ”