基于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。
相关推荐
雷神乐乐12 分钟前
File.separator与File.separatorChar的区别
java·路径分隔符
小刘|16 分钟前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
逊嘘35 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
筱源源37 分钟前
Elasticsearch-linux环境部署
linux·elasticsearch
morris13142 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员1 小时前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU1 小时前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie61 小时前
在IDEA中使用Git
java·git
Elaine2023911 小时前
06 网络编程基础
java·网络