基于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等字段及类型设定。

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推送消息,所以我直接从消息体属性获取,大致是这样的。

String author = getValueByPath(info, "author.name");

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

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

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

更新日期的处理

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

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的算法,内容很长:
很长的sha256值

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

Get INFO: Kelvin,Welcome to 1024!
File name MD5: bc4780da18a605a226798e46971e3fa1

实现代码:

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。
  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1024点线面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值