基于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。
相关推荐
考虑考虑14 小时前
Jpa使用union all
java·spring boot·后端
用户37215742613515 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊16 小时前
Java学习第22天 - 云原生与容器化
java
渣哥18 小时前
原来 Java 里线程安全集合有这么多种
java
间彧18 小时前
Spring Boot集成Spring Security完整指南
java
间彧18 小时前
Spring Secutiy基本原理及工作流程
java
Java水解19 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆21 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学1 天前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole1 天前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端