基于Git推送更新ES检索pdf方案的优化思路

写在前面

在之前的内容中我们已经介绍了创建gitbucket的webHook,使得仓库有更新时自动推送到我们定义的接口;然后Java读取仓库的文件转码写入ES库,这些核心流程已经实现。

1. 实现ES检索pdf等文件内容的插件

2. 基于GitBucket的Hook构建ES检索PDF等文档全栈方案

3. Java实现读取转码写入ES

在在我们的现有系统中,我们已经实现了自动化识别并记录文件类型的能力,无论是纯文本、PDF还是其他格式,都将作为一个ES属性加以记录,这对于后续根据不同文件类型实施针对性处理至关重要。

优化思路

当我们聚焦于Git库与Java开发环境时,我们应当进一步收集和整合文件的关键元数据,诸如文件标签以方便分类和检索,文件作者信息便于版权追踪和贡献度统计,以及文件的更新日期和版本信息,确保每一次变更的历史记录得以精确维护。

若将这一机制与Elasticsearch(ES)相结合,我们将增强对文件内容和元数据的实时索引能力,实现文件识别与Git仓库活动的联动。每当Git库中发生文件的新增、更新或删除操作时,系统都能自动感知并同步至ES,确保索引内容与实际仓库状态始终保持一致,从而实现高效的全文检索和分析。

具体的实现步骤及代码:

索引的映射结构优化

首先ES索引新增了更新时间、active等字段及类型设定。

http 复制代码
PUT /docwrite
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "title": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "fileType": {
        "type": "keyword"
      },
      "active": {
        "type": "boolean"
      },
      "upTime":{
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||epoch_millis"
      },
      "attachment": {
        "properties": {
          "content": {
            "type": "text",
            "analyzer": "ik_smart"
          }
        }
      }
    }
  }
}

文件作者与标签

作者信息不是解析的文档属性,由于我接收的是git推送消息,所以我直接从消息体属性获取,大致是这样的。

java 复制代码
String author = getValueByPath(info, "author.name");

文件标签是大多数文档都没有的,所以要么使用自定义的规则,要么就使用文件名分词,更高级的做法是做文章内容的摘要抽取关键词。 我的做法属于自定义规则类,因为我的文件总体上是属于git库的一部分,所以文件自身所在的目录就是它的类型,只要我们在创建文件夹时规范一下就可以了。山不过来我过去,业务上的规范设计能够使得代码逻辑更为简洁!

核心代码如下(当没有上级目录时,记作未定义):

java 复制代码
// 获取最后一级目录的名称,即文件的标签  
String tag = path.getParent() != null ? path.getParent().getFileName().toString() : "未定义";

更新日期的处理

git推送信息的日期字段是不太兼容的文本类型,我们将其变换为ES支持的时间戳类型:

java 复制代码
import java.time.OffsetDateTime;  
import java.time.format.DateTimeFormatter;

private static long dateToTimestamp(String dateStr) {  
  
    // 创建一个与ISO8601兼容的日期时间格式化器  
    DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;  
  
    // 解析字符串为OffsetDateTime对象  
    OffsetDateTime offsetDateTime = OffsetDateTime.parse(dateStr, formatter);  
  
    // 将OffsetDateTime转换为时间戳(毫秒)  
    return offsetDateTime.toInstant().toEpochMilli();  
}

文件唯一性识别

使用文件相对路径及文件名生成一段Hash值,如果使用SHA-256的算法,内容很长:

但如果截断的话会大幅升高冲突概率(实际上也很低),故而采用MD5摘要算法尚可以接受:

shell 复制代码
Get INFO: Kelvin,Welcome to 1024!
File name MD5: bc4780da18a605a226798e46971e3fa1

实现代码:

java 复制代码
import java.nio.charset.StandardCharsets;  
import java.security.MessageDigest;  
import java.security.NoSuchAlgorithmException;

public static String generateHash(String fileName) throws NoSuchAlgorithmException {  
    MessageDigest md = MessageDigest.getInstance("MD5"); // 获取MD5实例  
    byte[] bytesOfFileName = fileName.getBytes(StandardCharsets.UTF_8); // 将文件名转换为字节数组,确保编码正确  
    md.update(bytesOfFileName); // 更新摘要信息  
  
    byte[] digest = md.digest(); // 计算摘要  
    StringBuilder sb = new StringBuilder();  
  
    for (byte b : digest) {  
        sb.append(Integer.toHexString((b & 0xFF) | 0x100), 1, 3);  
    }  
  
    return sb.toString(); // 这就是MD5哈希值  
}

文件的删除

当推送信息里是删除操作时,我们需要将对应的索引文档也删除,那么沿用上面文件的MD5值进行判断,使用效率最高的按ID删除。

但是数据作为企业的宝贵资产,尤其是文档这种体量一般不大,更常见的做法是执行软删除,也就是找到文档将其标记为不可见(我已经提前设计了active布尔字段来记录)。

存在或发现的问题

  1. ES7.3实测无法索引docx和doc文档,content有值但是无法解析到附件成为可读的可搜索的内容,附件内容为空(附件中根本没有content这个字段,并非内容为空)。
  2. 理论上可以直接tika解析它的内容直接传递给ES。
相关推荐
AI多Agent协作实战派14 分钟前
AI多Agent协作系统实战(四十六):改了十次规则,AI员工还是老样子——会话缓存的坑
java·spring·缓存
一知半解仙25 分钟前
当机器人学会泛化,而我在写Java:一名后端开发者的2026年8月21日观察手记
java·开发语言·机器人
Elasticsearch2 小时前
让大模型思考,让小模型执行:在 Elastic Workflows 中拆分 LLM 成本
elasticsearch
葡萄成熟时 !9 小时前
JAVA 常用API学习笔记
java·笔记·学习
Lyyaoo.9 小时前
Spring Boot Validation 声明式参数校验
spring boot·后端·mysql
Rain的Java大神之路10 小时前
介绍一下分布式事务
java·分布式·后端·spring·spring cloud·架构·springcloud
吴声子夜歌10 小时前
Java面试题——基础(一)
java·开发语言
南城以南溫暖如初14711 小时前
外卖CPS实战指南:从技术选型到运营落地全流程解析
java·spring boot·mysql·架构·vue
傻啦嘿哟11 小时前
英雄联盟皮肤爬虫:爬取全皮肤价格与特效,做比价工具
java·c++·爬虫
Elastic 中国社区官方博客12 小时前
ES95:面向 Elasticsearch 时间序列指标的自适应压缩
大数据·运维·elasticsearch·搜索引擎·架构·全文检索