目录
- 一、项目背景与技术选型
- 技术选型
- 二、环境准备
- 2.1 Maven依赖配置
- 2.2 配置文件
- 三、核心功能实现步骤
- 3.1 安装ElasticSearch插件
- 3.2 创建文档抽取管道
- 3.2.1 定义Pipeline
- 3.3 定义索引与映射
- 3.3.1 创建索引
- 3.4 Java代码实现文档处理
- 3.4.1 文件上传接口
- 3.5 全文检索与高亮分词
- 3.5.1 搜索接口
- 四、性能优化与注意事项
- 4.1 缓存策略
- 4.2 分页与过滤
- 4.3 安全与容错
- 五、代码整合
- 5.1 配置类(ElasticSearch连接)
- 5.2 高亮结果返回示例
- 六、从零到一的文档搜索闭环
- 七、行动号召:立即动手实践!
一、项目背景与技术选型
在企业级应用中,文档内容的智能化检索是一个高频需求。例如:
- 上传PDF/Word文档后自动抽取文本
- 支持中文分词和模糊匹配
- 搜索结果高亮显示关键词
技术选型
| 技术 | 作用 |
|---|---|
| SpringBoot | 快速构建微服务 |
| ElasticSearch | 实现全文检索与高亮功能 |
| Jieba分词插件 | 中文分词支持 |
| Ingest Attachment Processor Plugin | 文档内容抽取(PDF/Word等) |
二、环境准备
2.1 Maven依赖配置
<!-- pom.XML -->
<dependencies>
<!-- SpringBoot基础 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Elasticsearch连接 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- 文件处理工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<!-- Jieba分词插件 -->
<dependency>
<groupId>com.nlp</groupId>
<artifactId>elasticsearch-analysis-jieba</artifactId>
<version>7.17.0</version>
</dependency>
</dependencies>
2.2 配置文件
# application.yml
spring:
data:
elasticsearch:
cluster-name: my-cluster
cluster-nodes: localhost:9200
elasticsearch:
rest:
uris: http://localhost:9200
username: elastic
password: your_password
三、核心功能实现步骤
3.1 安装ElasticSearch插件
Ingest Attachment Processor Plugin
# 安装插件(本地ES) elasticsearch-plugin install ingest-attachment # 安装插件(docker容器内) docker exec -it elasticsearch bin/elasticsearch-plugin install ingest-attachment
注意:确保插件版本与ES版本匹配!重启ES后生效。
Jieba中文分词插件
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-jieba/releases/download/v7.17.0/elasticsearch-analysis-jieba-7.17.0.zip
3.2 创建文档抽取管道
ElasticSearch的Ingest Pipeline用于自动化处理上传的文件内容。
3.2.1 定义Pipeline
PUT _ingest/pipeline/attachment-extract
{
"description": "Extract attachment content",
"processors": [
{
"attachment": {
"field": "content",
"target_field": "attachment",
"ignore_missing": true
}
},
{
"remove": {
"field": "content"
}
}
]
}
关键点:
- attachment处理器将Base64编码的文件内容解析为文本。
- remove处理器删除原始二进制字段,保留提取后的文本。
3.3 定义索引与映射
索引的mapping和settings决定了数据存储格式和分词规则。
3.3.1 创建索引
PUT /fileinfo
{
"mappings": {
"properties": {
"id": { "type": "keyword" },
"fileName": { "type": "text" },
"fileType": { "type": "keyword" },
"attachment": {
"properties": {
"content": { "type": javascript"text", "analyzer": "jieba" } // 使用Jieba分词
}
}
}
},
"settings": {
"analysis": {
"analyzer": {
"jieba": {
"type": "custom",
"tokenizer": "jieba_tokenizer"
}
}
}
}
}
注意:attachment.content字段必须使用分词器,否则全文检索会失败!
3.4 Java代码实现文档处理
3.4.1 文件上传接口
@RestController
@RequestMapping("/api/files")
public class FileUploadController {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
// 1. 文件转Base64
String base64Content = Base64.getEncoder().encodeToString(file.getBytes());
// 2. 构造文档对象
Map<String, Object> document = new HashMap<>();
document.put("id", UUID.randomUUID().toString());
document.put("fileName", file.getOriginalFilename());
document.put("fileType", getFileType(file.getOriginalFilename()));
document.put("content", base64Content); // 二进制字段
// 3. 使用Pipeline处理并索引文档
IndexRequest request = new IndexRequest("fileinfo")
.setId(document.get("id编程客栈").toString())
.setPipeline("attachment-extract") // 关键:绑定Pipeline
.setSource(document);
elasticsearchRestTemplate.index(request);
return ResponseEntity.ok("文件已成功索引");
}
private String getContentType(MultipartFile file) {
String originalFilename = file.getOriginalFilename();
if (originalFilename.endsWith(".pdf")) {
return "application/pdf";
} else if (originalFilename.endsWith(".docx")) {
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
}
return "application/octet-stream";
}
}
代码解析:
- Base64.getEncoder() 将文件转为Base64字符串,便于传输。
- setPipeline("attachment-extract") 调用预定义的Pipeline处理内容。
- elasticsearchRestTemplate.index() 执行索引操作。
3.5 全文检索与高亮分词
3.5.1 搜索接口
@GetMapping("/search")
public ResponseEntity<Map<String, Object>> searchFiles(@RequestParam String keyword) {
// 1. 构建查询
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("attachment.content", keyword)
.analyzer("jieba") // 使用Jieba分词
.fuzziness("AUTO"));
// 2. 启用高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("attachment.content").preTags("<mark>").postTags("</mark>");
sourceBuilder.highlighter(highlightBuilder);
// 3. 执行搜索
SearchRequest searchRequest = new SearchRequest("fileinfo");
searchRequest.source(sourceBuilder);
SearchResponse response = elasticsearchRestTemplate.search(searchRequest);
// 4. 提取高亮结果
List<Map<String, Object>> results = new ArrayList<>();
for (SearchHit hit : response.getHits().getHits()) {
Map<String, Object> source = hit.getSourceAsMap();
Map<String, HighlightField> highlights = hit.getHighlightFields();
HighlightField contentHighlight = highlights.get("attachment.content");
if (contentHighlight != null) {
source.put("highlight", contentHighlight.fragments()[0].string());
}
results.add(source);
http://www.devze.com }
return ResponseEntity.ok(Collections.singletonMap("results", results));
}
关键点:
- matchQuery("attachment.content", keyword) 对内容字段进行分词匹配。
- HighlightBuilder 控制高亮标签(如<mark>)。
- 搜索结果中highlight字段包含高亮片段。
四、性能优化与注意事项
4.1 缓存策略
- ElasticSearch缓存:启用
request_cache减少重复查询开销。 - 应用层缓存:使用Redis缓存高频搜索结果。
4.2 分页与过滤
// 分页示例
sourceBuilder.from(0).size(10); // 限制每页10条
sourceBuilder.sort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)); // 按时间排序
4.3 安全与容错
- 文件类型校验:防止非法文件上传。
- 异常处理:捕获
ElasticsearchException并返回友好的错误信息。
五、代码整合
5.1 配置类(ElasticSearch连接)
@Configuration
public class jsElasticsearchConfig {
@Value("${spring.elasticsearch.rest.uris}")
private String esUri;
@Bean
public RestHighLevelClient elasticsearchClient() {
return new RestHighLevelClient(
RestClient.builder(new HttpHost(esUri.split(":")[0], Integer.parseInt(esUri.split(":")[1]), "http")));
}
@Bean
public ElasticsearchRestTemplate elasticsearchRestTemplate(RestHighLevelClient client) {
return new ElasticsearchRestTemplate(client);
}
}
5.2 高亮结果返回示例
{
"results": [
{
"id": "123",
"fileName": "进口红酒.pdf",
"fileType": "pdf",
"attachment": {
"content": "这款红酒产自法国波尔多地区,口感醇厚..."
},
"highlight": "这款红酒产自法国波尔多地区,<mark>口感醇厚</mark>..."
}
]
}
六、从零到一的文档搜索闭环
| 步骤 | 核心代码/配置 | 作用 |
|---|---|---|
| 1. 依赖配置 | pom.xml | 引入ElasticSearch和分词插件 |
| 2. 管道定义 | PUT _ingest/pipeline/attachment-extract | 自动抽取文件内容 |
| 3. 索引映射 | PUT /fileinfo | 定义字段类型和分词规则 |
| 4. 文件上传 | FileUploadController.uploadFile() | 将文件转为Base64并索引 |
| 5. 全文搜索 | FileUploadController.searchFiles() | 使用Jieba分词和高亮 |
七、行动号召:立即动手实践!
“文档检索不再是难题!现在就搭建你的智能搜索系统!”
- 尝试基础功能:上传一个PDF并验证内容抽取是否成功。
- 挑战分词优化:自定义Jieba分词词典,提升匹配准确率。
- 扩展搜索维度:添加按文件类型、时间范围的过滤功能。
以上就是基于SpringBoot+ElasticSearch实现文档智能化检索的完整指南的详细内容,更多关于SpringBoot ElasticSearch文档检索的资料请关注编程客栈(www.cppcnhttp://www.devze.coms.com)其它相关文章!
加载中,请稍侯......
精彩评论