SpringBoot + Elasticsearch7.6實現(xiàn)簡單查詢及高亮分詞查詢
點擊關(guān)注公眾號,Java干貨及時送達

來源:blog.csdn.net/weixin_44102992/article/details/108033164
前言
該文章需要提前準備好Elasticsearch7.6以及ik分詞器的環(huán)境,如果還沒準備好的可以看看
https://blog.csdn.net/weixin_44102992/article/details/107954129
集成環(huán)境準備
1.導入spring-data-elasticsearch依賴
版本需要與Elasticsearch一致,還需要注意自己的springboot版本是否支持
本文springboot為2.3,依賴也為2.3,elasticsearch為7.6.2

<dependency>
??<groupId>org.springframework.datagroupId>
??<artifactId>spring-data-elasticsearchartifactId>
??<version>${version}.RELEASEversion>
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.實體類準備
關(guān)于實體類中的幾個注解,不清楚的可以去查看文檔,這里不過多介紹了
@Data
@Document(indexName?=?"user")//索引名稱?建議與實體類一致
public?class?User?{
????@Id
????private?Integer?id;
????@Field(type?=?FieldType.Auto)//自動檢測類型
????private?Integer?age;
????@Field(type?=?FieldType.Keyword)//手動設(shè)置為keyword??但同時也就不能分詞
????private?String?name;
????@Field(type?=?FieldType.Text,analyzer?=?"ik_smart",searchAnalyzer?=?"ik_max_word")//設(shè)置為text??可以分詞
????private?String?info;
}
4.Elasticsearch Service準備
ElasticsearchRepository<,>第一個就是所準備的實體類,第二個是id的類型
繼承完這個會提供最基本的增刪改查方法,也可以自己定義一些,自己定義的方法命名需要符合規(guī)則,并不需要自己去實現(xiàn)
public?interface?EsUserService?extends?ElasticsearchRepository<User,Integer>?{
????//根據(jù)name查詢
????List?findByName(String?name) ;
????//根據(jù)name和info查詢
????List?findByNameAndInfo(String?name,String?info) ;
}
簡單查詢
這里直接使用假數(shù)據(jù)并沒有連接數(shù)據(jù)庫,還需要注意幾個點:
elasticsearchTemplate需要采用ElasticsearchRestTemplate 原來的已經(jīng)過時了 elasticsearch的mapping沒有自動生成,這導致了我們在實體類中指定的分詞器沒有生效,所以我在導入數(shù)據(jù)的同時,手動導入了mapping LogAnnotation是我自定義的注解,大家可以直接去掉
controller如下:
@RestController
public?class?EsController?{
????@Autowired
????private?ElasticsearchRestTemplate?elasticsearchTemplate;
????@Autowired
????private?EsUserService?esUserService;
????private?String[]?names={"諸葛亮","曹操","李白","韓信","趙云","小喬","狄仁杰","李四","諸小明","王五"};
????private?String[]?infos={"我來自中國的一個小鄉(xiāng)村,地處湖南省","我來自中國的一個大城市,名叫上海,人們稱作魔都"
????????????,"我來自東北,家住大囤里,一口大碴子話"};
????@LogAnnotation(requestRemark?=?"存數(shù)據(jù)")
????@GetMapping("saveUser")
????public?ResultVO?saveUser(){
?????//添加索引mapping????索引會自動創(chuàng)建但mapping自只用默認的這會導致分詞器不生效?所以這里我們手動導入mapping
????????elasticsearchTemplate.putMapping(User.class);
????????Random?random?=?new?Random();
????????List?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?users1?=?esUserService.saveAll(users);
????????return?new?ResultVO(users1);
????}
????@LogAnnotation(requestRemark?=?"根據(jù)id查詢數(shù)據(jù)")
????@GetMapping("getDataById")
????public?ResultVO?getDataById(Integer?id){
????????return?new?ResultVO(esUserService.findById(id));
????}
????@LogAnnotation(requestRemark?=?"分頁查詢所有數(shù)據(jù)")
????@GetMapping("getAllDataByPage")
????public?ResultVO?getAllDataByPage(){
????????//本該傳入page和size,這里為了方便就直接寫死了
????????Pageable?page?=?PageRequest.of(0,10,?Sort.Direction.ASC,"id");
????????Page?all?=?esUserService.findAll(page);
????????return?new?ResultVO(all.getContent());
????}
????@LogAnnotation(requestRemark?=?"根據(jù)名字查詢")
????@GetMapping("getDataByName")
????public?ResultVO?getDataByName(String?name){
????????return?new?ResultVO(esUserService.findByName(name));
????}
????@LogAnnotation(requestRemark?=?"根據(jù)名字和介紹查詢")
????@GetMapping("getDataByNameAndInfo")
????public?ResultVO?getDataByNameAndInfo(String?name,String?info){
????????//這里是查詢兩個字段取交集,即代表兩個條件需要同時滿足
????????return?new?ResultVO(esUserService.findByNameAndInfo(name,info));
????}
}
測試結(jié)果:




分詞高亮查詢
????@LogAnnotation(requestRemark?=?"查詢高亮顯示")
????@GetMapping("getHightByUser")
????public?ResultVO?getHightByUser(String?value){
????????//根據(jù)一個值查詢多個字段??并高亮顯示??這里的查詢是取并集,即多個字段只需要有一個字段滿足即可
????????//需要查詢的字段
????????BoolQueryBuilder?boolQueryBuilder=?QueryBuilders.boolQuery()
????????????????.should(QueryBuilders.matchQuery("info",value))
????????????????.should(QueryBuilders.matchQuery("name",value));
??//構(gòu)建高亮查詢
????????NativeSearchQuery?searchQuery?=?new?NativeSearchQueryBuilder()
????????????????.withQuery(boolQueryBuilder)
????????????????.withHighlightFields(
????????????????????????new?HighlightBuilder.Field("info")
????????????????????????,new?HighlightBuilder.Field("name"))
????????????????.withHighlightBuilder(new?HighlightBuilder().preTags("").postTags(""))
????????????????.build();
????????//查詢
????????SearchHits?search?=?elasticsearchTemplate.search(searchQuery,?User.class);
????????//得到查詢返回的內(nèi)容
????????List>?searchHits?=?search.getSearchHits();
????????//設(shè)置一個最后需要返回的實體類集合
????????List?users?=?new?ArrayList<>();
????????//遍歷返回的內(nèi)容進行處理
????????for(SearchHit?searchHit:searchHits){
????????????//高亮的內(nèi)容
????????????Map>?highlightFields?=?searchHit.getHighlightFields();
????????????//將高亮的內(nèi)容填充到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);
????}
測試結(jié)果:

往 期 推 薦
1、致歉!抖音Semi Design承認參考阿里Ant Design
2、對比7種分布式事務方案,還是偏愛阿里開源的Seata,真香!
點分享
點收藏
點點贊
點在看
評論
圖片
表情





