{
"tokens": [
{
"token": "测",
"start_offset": 0,
"end_offset": 1,
"type": "<IDEOGRAPHIC>",
"position": 0
},
{
"token": "试",
"start_offset": 1,
"end_offset": 2,
"type": "<IDEOGRAPHIC>",
"position": 1
},
{
"token": "单",
"start_offset": 2,
"end_offset": 3,
"type": "<IDEOGRAPHIC>",
"position": 2
},
{
"token": "词",
"start_offset": 3,
"end_offset": 4,
"type": "<IDEOGRAPHIC>",
"position": 3
}
]
}
这样的结果显然不符合我们的使用要求,所以我们需要下载 ES 对应版本的中文分词器。
将解压后的后的文件夹放入 ES 根目录下的 plugins 目录下,重启 ES 即可使用。
我们这次加入新的查询参数"analyzer":“ik_max_word”。
# GET http://localhost:9200/_analyze
{
"text":"测试单词",
"analyzer":"ik_smart"
}
- ik_max_word:会将文本做最细粒度的拆分。
- ik_smart:会将文本做最粗粒度的拆分。
使用中文分词后的结果为:
{
"tokens": [
{
"token": "测试",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "单词",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
}
]
}
ES 中也可以进行扩展词汇,首先查询
ES 中也可以进行扩展词汇,首先查询
#GET http://localhost:9200/_analyze
{
"text":"弗雷尔卓德",
"analyzer":"ik_max_word"
}
仅仅可以得到每个字的分词结果,我们需要做的就是使分词器识别到弗雷尔卓德也是一个词语。
{
"tokens": [
{
"token": "弗",
"start_offset": 0,
"end_offset": 1,
"type": "CN_CHAR",
"position": 0
},
{
"token": "雷",
"start_offset": 1,
"end_offset": 2,
"type": "CN_CHAR",
"position": 1
},
{
"token": "尔",
"start_offset": 2,
"end_offset": 3,
"type": "CN_CHAR",
"position": 2
},
{
"token": "卓",
"start_offset": 3,
"end_offset": 4,
"type": "CN_CHAR",
"position": 3
},
{
"token": "德",
"start_offset": 4,
"end_offset": 5,
"type": "CN_CHAR",
"position": 4
}
]
}
- 首先进入 ES 根目录中的 plugins 文件夹下的 ik 文件夹,进入 config 目录,创建 custom.dic文件,写入“弗雷尔卓德”。
- 同时打开 IKAnalyzer.cfg.xml 文件,将新建的 custom.dic 配置其中。
- 重启 ES 服务器 。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">custom.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
扩展后再次查询
# GET http://localhost:9200/_analyze
{
"text":"测试单词",
"analyzer":"ik_max_word"
}
返回结果如下:
{
"tokens": [
{
"token": "弗雷尔卓德",
"start_offset": 0,
"end_offset": 5,
"type": "CN_WORD",
"position": 0
}
]
}
整合springboot
引入依赖:
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
配置:
spring:
elasticsearch:
uris: http://localhost:9200
实体类:
package com.example.modules.es.bean.es;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
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.FieldType;
/**
* @author yinqi
* @description
* @create 2024/2/4 9:35
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "blog_index", shards = 3, replicas = 0)
@JsonIgnoreProperties(ignoreUnknown = true)
@Builder
public class Blog {
@Id
private String id;
private String title;
@Field(type = FieldType.Text, analyzer = "ik_smart")
private String content;
private int num;
}
高亮查询的返回对象:
package com.example.modules.es.bean.es;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 查询Blog后,高亮返回查询结果
* @author yinqi
* @description
* @create 2024/2/19 11:03
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class BlogHighlight {
private String id;
private String title;
private String content;
private int num;
private float score;
//高亮标题
private String highlightedTitle;
//高亮内容
private String highlightedContent;
}
控制层:
package com.example.modules.es.controller;
import com.example.modules.es.bean.es.Blog;
import com.example.modules.es.bean.es.BlogHighlight;
import com.example.modules.es.service.BlogRepository;
import com.example.modules.es.service.BlogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author yinqi
* @description
* @create 2024/2/4 9:45
**/
@RestController
@RequestMapping("/es/blog")
@Api(tags = "es--BlogController 控制层")
public class BlogController {
@Autowired
private BlogService userService;
@Autowired
private BlogRepository blogRepository;
@GetMapping("/saveTestData")
@ApiOperation("保存测试数据")
public void saveTestData(){
userService.saveTestData();
}
@PostMapping("/save")
@ApiOperation("保存")
public void save(@RequestBody Blog blog){
userService.save(blog);
}
@DeleteMapping("/delete")
@ApiOperation("根据id删除")
public void delete(@RequestParam String id){
userService.delete(id);
}
@PutMapping("/update")
@ApiOperation("更新")
public void update(@RequestBody Blog blog){
userService.update(blog);
}
@GetMapping("/findAll")
@ApiOperation("查询所有")
public List<Blog> findAll(){
List<Blog> blogs = userService.findAll();
return blogs;
}
@GetMapping("/searchByKeyword")
@ApiOperation("根据关键词查询")
public List<Blog> searchByKeyword(@RequestParam String keyword){
List<Blog> blogs = userService.searchByKeyword(keyword);
return blogs;
}
@GetMapping("/likeSearch")
@ApiOperation("模糊查询")
public List<Blog> likeSearch(@RequestParam String keyword){
List<Blog> blogs = userService.likeSearch(keyword);
return blogs;
}
@GetMapping("/combinationSearch")
@ApiOperation("组合查询")
public List<Blog> combinationSearch(@RequestParam String keyword){
List<Blog> blogs = userService.combinationSearch(keyword);
return blogs;
}
@GetMapping("/highlightSearch")
@ApiOperation("根据标题和内容高亮查询")
public List<SearchHit<Blog>> highlightSearch(@RequestParam String title, @RequestParam String content){
List<SearchHit<Blog>> byTitleOrContent = blogRepository.findByTitleOrContent(title, content);
return byTitleOrContent;
}
@GetMapping("/highlightSearchBykeyword")
@ApiOperation("根据关键词高亮查询")
public List<BlogHighlight> highlightSearchBykeyword(@RequestParam String keyword){
List<BlogHighlight> blogHighlights = userService.highlightSearchBykeyword(keyword);
return blogHighlights;
}
}
BlogRepository:
package com.example.modules.es.service;
import com.example.modules.es.bean.es.Blog;
import org.springframework.data.elasticsearch.annotations.Highlight;
import org.springframework.data.elasticsearch.annotations.HighlightField;
import org.springframework.data.elasticsearch.annotations.HighlightParameters;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface BlogRepository extends ElasticsearchRepository<Blog, String> {
/**
* 根据内容标题查询
* @param title 标题
* @param content 内容
* @return 返回关键字高亮的结果集
*/
@Highlight(
fields = {@HighlightField(name = "title"), @HighlightField(name = "content")},
parameters = @HighlightParameters(preTags = {"<span style='color:yellow'>"}, postTags = {"</span>"}, numberOfFragments = 0)
)
List<SearchHit<Blog>> findByTitleOrContent(String title, String content);
}
BlogService接口:
package com.example.modules.es.service;
import com.example.modules.es.bean.es.Blog;
import com.example.modules.es.bean.es.BlogHighlight;
import java.util.List;
public interface BlogService {
/**
* 造测试数据
*/
void saveTestData();
/**
* 保存
* @param blog
*/
void save(Blog blog);
/**
* 删除
* @param id
*/
void delete(String id);
/**
* 更新
* @param blog
*/
void update(Blog blog);
/**
* 查询所有
* @return
*/
List<Blog> findAll();
/**
* 根据关键词查询
* @param keyword
* @return
*/
List<Blog> searchByKeyword(String keyword);
/**
* 根据关键词高亮查询
* @param keyword
* @return
*/
List<BlogHighlight> highlightSearchBykeyword(String keyword);
/**
* 组合查询
* @return
*/
List<Blog> combinationSearch(String keyword);
/**
* 模糊查询
* @param keyword
* @return
*/
List<Blog> likeSearch(String keyword);
}
BlogServiceImpl:
package com.example.modules.es.service.impl;
import com.example.modules.es.bean.es.Blog;
import com.example.modules.es.bean.es.BlogHighlight;
import com.example.modules.es.service.BlogRepository;
import com.example.modules.es.service.BlogService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* @author yinqi
* @description
* @create 2024/2/4 9:45
**/
@Service
public class BlogServiceImpl implements BlogService {
@Autowired
private BlogRepository blogRepository;
@Autowired
private RestHighLevelClient restHighLevelClient;
@Override
public void saveTestData() {
Blog blog1 = Blog.builder()
.title("2024 年技术招聘现状")
.num(12)
.content("时下 ChatGPT 已成为不少人编码、写作、搜索的辅助工具。然而,不久之前技术招聘平台 CoderPad 发布了一份《2024 年技术招聘现状》报告显示,23% 的招聘人员和招聘经理认为候选人在技术测试或者编码面试中使用 AI 是作弊行为")
.build();
Blog blog2 = Blog.builder()
.title("ChatGPT 是否扼杀了软件工程基本的编码能力")
.num(13)
.content("不过现实来看,有多少人会在编码面试中使用 ChatGPT?以及 ChatGPT 来协助“作弊”难易度如何?ChatGPT 是否扼杀了软件工程基本的编码能力?这可以让更多的程序员拿到门槛较高的大厂 offer 吗?")
.build();
Blog blog3 = Blog.builder()
.title("你好,中国")
.num(18)
.content("你好,中国。苹果;对此,一位前 Google 工程师 Michael Mroczka 在 Interviewing.io 平台上进行了一项实验,招募了一些专业的采访者和用户进行了作弊实验,揭晓在技术面试中用 ChatGPT 作弊究竟有多难。")
.build();
Blog blog4 = Blog.builder()
.title("借助 ChatGPT 工具")
.num(20)
.content("借助 ChatGPT 工具,候选者在解决三种不同类型的面试问题时,通过率分别为:73%(LeetCode 原版问题)、67%(修改后的 LeetCode 问题)、25%(面试官自定义的面试问题)")
.build();
Blog blog5 = Blog.builder()
.title("2024 ,Android 15 预览版来了")
.num(25)
.content("日前,Android 15 发布了 Preview 1 预览版,预览计划将从 2024 年 2 月持续到 Android 15 公开发布(预计 10 月),3月是开发者预览版 2,4 月将推出 Beta 1,5 月将推出 Beta 2,6 月的 Beta 3、7 月的 Beta 4 和然后发布正式版。\n" +
"版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。")
.build();
Blog blog6 = Blog.builder()
.title("宝马确认发生数据泄露事件")
.num(78)
.content("据报道,汽车巨头宝马的云存储服务器发生配置错误事件,导致私钥和内部数据等敏感信息暴露。研究人员 Can Yoleri 表示,其在例行扫描时发现宝马开发环境中的微软 Azure 托管存储服务器(也称“存储桶”)被配置为公共而非私有。")
.build();
Blog blog7 = Blog.builder()
.title("魅族停止传统手机项目,后续将推出 AI 终端产品")
.num(25)
.content("2 月 18 日,魅族官方微博宣布将停止传统手机新项目的开发,转型“All in AI”。在视频中,星纪魅族 CEO 沈子瑜对比了 AI Pin 和 Rabbit R1 等产品,称其带来了非常好的答案,但其实不够完美。沈子瑜还表示魅族在软硬件都有更大的优势,后续将推出 AI 终端产品,但并未说明具体产品形态。")
.build();
Blog blog8 = Blog.builder()
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数大数据工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/b4cd34264824cf66d3b9deef3ce668e7.png)
![img](https://img-blog.csdnimg.cn/img_convert/e482a706dfd5775bc0d6813ed6b949dc.png)
![img](https://img-blog.csdnimg.cn/img_convert/de06352f29c3431f502ad36b1ac01891.png)
![img](https://img-blog.csdnimg.cn/img_convert/f8c85d3904be34e7f4d012cb7840af99.png)
![img](https://img-blog.csdnimg.cn/img_convert/02cfb9a3f07e74a8fa1d52af6fca6542.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)**
![img](https://img-blog.csdnimg.cn/img_convert/d96a2a13782a7b551c16fa9102a9af2d.png)
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
[外链图片转存中...(img-LaRQoqZk-1712959435101)]
[外链图片转存中...(img-apSMLn7N-1712959435102)]
[外链图片转存中...(img-DYxwWzF6-1712959435102)]
[外链图片转存中...(img-zuppGzfz-1712959435102)]
[外链图片转存中...(img-R4my4kZW-1712959435103)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)**
[外链图片转存中...(img-aoDH7hEO-1712959435103)]
**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**