ElasticSearch 实现 全文检索 支持(PDF、TXT、Word、HTML等文件)通过 ingest-attachment 插件实现 文档的检索

一、Attachment 介绍

Attachment 插件是 Elasticsearch 中的一种插件,允许将各种二进制文件(如PDF、Word文档等)以及它们的内容索引到 Elasticsearch 中。插件使用 Apache Tika 库来解析和提取二进制文件的内容。通过使用 Attachment 插件,可以轻松地在 Elasticsearch 中建立全文搜索功能,而无需事先转换二进制文件为文本。

优点:

  1. 可以将各种类型的二进制文件以原始形式存储在 Elasticsearch 中。这使得保存和访问二进制文件变得更加简单和高效。

  2. 插件使用 Apache Tika 库来解析和提取二进制文件的内容,因此可以提取并存储内容、元数据以及格式化的文本数据。这使得 Elasticsearch 可以轻松地对文档执行全文搜索以及文档内容的其他分析操作。

  3. 在 Elasticsearch 中使用 Attachment 插件,可以轻松地实现以下一些功能:搜索文档、生成全文搜索报告、自动标记文件、提取数据并进行分析,在文档中查找特定项等。

缺点:

  1. Attachment 插件对性能有一定的影响,因为执行全文搜索需要解析和提取二进制文件的内容。如果处理大量的二进制文件,可能会影响搜索性能。

  2. Attachment 插件有一些限制,例如插件不支持对二进制文件进行过滤或排除,因此如果文件内容包含敏感信息,则不应使用 Attachment 插件进行索引。

二、初始化 ingest-attachment

1、windows安装

1、先在ES的bin目录下执行命令 安装 ngest-attachment插件

java 复制代码
elasticsearch-plugin install ingest-attachment

作者已经安装过了 所以不能重复安装,插件下载过程中会出现

2、Liunx安装

通过官网下载,找到对应的版本号:attachment下载网站

下载好后上传到服务器,进入elasticsearch安装目下的bin目录下。

执行sudo ./elasticsearch-plugin install file:///home/ingest-attachment-7.9.0.zip 即可

重启ES 打印 [apYgDEl] loaded plugin [ingest-attachment] 表示安装成功

3、小结

安装完成后需要重新启动ES

接下来我们需要创建一个关于ingest-attachment的文本抽取管道

java 复制代码
PUT /_ingest/pipeline/attachment
{
    "description": "Extract attachment information",
    "processors": [
        {
            "attachment": {
                "field": "content",
                "ignore_missing": true
            }
        },
        {
            "remove": {
                "field": "content"
            }
        }
    ]
}

后续我们的文件需要base64后储存到 attachment.content 索引字段中

三、如何应用?

1、通过命令语句简易检索

创建一个ES 索引 并且添加一些测试数据

java 复制代码
POST /pdf_data/_doc?pretty
{

  "id": "3",

  "name": "面试题文件1.pdf",

  "age": 18,

  "type": "file",

  "money": 1111,

  "createBy": "阿杰",

  "createTime": "2022-11-03T10:41:51.851Z",

  "attachment": {

    "content": "面试官:如何保证消息不被重复消费啊?如何保证消费的时候是幂等的啊?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?",

    "date": "2022-11-02T10:41:51.851Z",

    "language": "en"

  }
}

通过插入的文档内容为条件进行检索

java 复制代码
# 简单 单条件查询 文档内容检索
GET /pdf_data/_search
{
  "query": {
    "match": {
      "attachment.content": "面试官:如何保证消息不被重复消费啊?如何保证消费的时候是幂等的啊?"
    }
  }
}

2、整合java代码实现ES通过ingest-attachment进行全文检索

1、首先将文件转为BASE64进行ES数据插入

java 复制代码
/**
     * 将文件 文档信息储存到数据中
     * @param file
     * @return
     */
    @PostMapping("/insertFile")
    @ApiOperation(value="创建索引ES-传入ES索引-传入文件", notes="创建索引ES-传入ES索引-传入文件")
    public IndexResponse insertFile(@RequestAttribute("file") MultipartFile file,@RequestParam("indexName")String indexName){
        FileObj fileObj = new FileObj();
        fileObj.setId(String.valueOf(System.currentTimeMillis()));
        fileObj.setName(file.getOriginalFilename());
        fileObj.setType(file.getName().substring(file.getName().lastIndexOf(".") + 1));
        fileObj.setCreateBy(RandomNameGenerator.generateRandomName());
        fileObj.setCreateTime(String.valueOf(System.currentTimeMillis()));
        fileObj.setAge(RandomNameGenerator.getAge());
        fileObj.setMoney(RandomNameGenerator.getMoney());
        // 文件转base64
        byte[] bytes = new byte[0];
        try {
            bytes = file.getBytes();
            //将文件内容转化为base64编码
            String base64 = Base64.getEncoder().encodeToString(bytes);
            fileObj.setContent(base64);

           IndexResponse indexResponse=  ElasticsearchUtil.upload(fileObj,indexName);
            if (0==indexResponse.status().getStatus()){
                // 索引创建并插入数据成功
                System.out.println("索引创建并插入数据成功");
            }
            return indexResponse;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2、创建索引、插入数据,并且将文档数据抽取到管道中

java 复制代码
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private  static  RestHighLevelClient levelClient;

    @PostConstruct
    public void initClient() {
        levelClient = this.restHighLevelClient;
    }

/**
     * 创建索引并插入数据
     * @param file
     * @param indexName
     * @return
     * @throws IOException
     */
    public static IndexResponse upload(FileObj file,String indexName) throws IOException {
        // TODO 创建前需要判断当前文档是否已经存在
        if (!isIndexExist(indexName)) {
            CreateIndexRequest request = new CreateIndexRequest(indexName);
        // 如果需要ik分词器就添加配置,不需要就注释掉 
            // 添加 IK 分词器设置  ik_max_word
//            request.settings(Settings.builder()
//                    .put("index.analysis.analyzer.default.type", "ik_max_word")
//                    .put("index.analysis.analyzer.default.use_smart", "true")
//            );
            
            // 添加 IK 分词器设置 ik_smart 
            request.settings(Settings.builder()
                    .put("index.analysis.analyzer.default.type", "ik_smart")
            );
            CreateIndexResponse response = levelClient.indices().create(request, RequestOptions.DEFAULT);
            log.info("执行建立成功?" + response.isAcknowledged());
        }
        IndexRequest indexRequest = new IndexRequest(indexName);
        //上传同时,使用attachment pipline进行提取文件
        indexRequest.source(JSON.toJSONString(file), XContentType.JSON);
        indexRequest.setPipeline("attachment");
        IndexResponse indexResponse= levelClient.index(indexRequest,RequestOptions.DEFAULT);
        System.out.println(indexResponse);
        return indexResponse;
    }

3、其他代码补充

ES Config 配置类

java 复制代码
/**
 * ES配置类
 * author: 阿杰
 */
@Configuration
public class ElasticSearchClientConfig {

    /**
     * ES 地址:127.0.0.1:9200
     */
    @Value("${es.ip}")
    private String hostName;

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        String[] points = hostName.split(",");
        HttpHost[] httpHosts = new HttpHost[points.length];
        for (int i = 0; i < points.length; i++) {
            String point = points[i];
            httpHosts[i] = new HttpHost(point.split(":")[0], Integer.parseInt(point.split(":")[1]), "http");
        }
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(httpHosts));
        return client;
    }

    @Bean
    public ElasticsearchUtil elasticSearchUtil() {
        return new ElasticsearchUtil();
    }


}

数据插入使用的实体类

java 复制代码
/**
 * author: 阿杰
 */
@Data
public class FileObj {
    /**
     * 用于存储文件id
     */
    String id;
    /**
     * 文件名
     */
    String name;
    /**
     * 文件的type,pdf,word,or txt
     */
    String type;
    /**
     * 数据插入时间
     */
    String createTime;
    /**
     * 当前数据所属人员
     */
    String createBy;

    /**
     * 当前数据所属人员的年龄
     */
    int age;

    /**
     * 当前数据所属人员的资产
     */
    int money;

    /**
     * 文件转化成base64编码后所有的内容。
     */
    String content;
}

完整代码可通过: 完整代码包下载

制作不易,给个小赞!

相关推荐
hengzhepa16 分钟前
ElasticSearch备考 -- Search across cluster
学习·elasticsearch·搜索引擎·全文检索·es
Elastic 中国社区官方博客2 小时前
Elasticsearch:使用 LLM 实现传统搜索自动化
大数据·人工智能·elasticsearch·搜索引擎·ai·自动化·全文检索
慕雪华年3 小时前
【WSL】wsl中ubuntu无法通过useradd添加用户
linux·ubuntu·elasticsearch
Elastic 中国社区官方博客5 小时前
使用 Vertex AI Gemini 模型和 Elasticsearch Playground 快速创建 RAG 应用程序
大数据·人工智能·elasticsearch·搜索引擎·全文检索
alfiy6 小时前
Elasticsearch学习笔记(四) Elasticsearch集群安全配置一
笔记·学习·elasticsearch
alfiy6 小时前
Elasticsearch学习笔记(五)Elastic stack安全配置二
笔记·学习·elasticsearch
丶21361 天前
【大数据】Elasticsearch 实战应用总结
大数据·elasticsearch·搜索引擎
闲人编程1 天前
elasticsearch实战应用
大数据·python·elasticsearch·实战应用
世俗ˊ1 天前
Elasticsearch学习笔记(3)
笔记·学习·elasticsearch
weixin_466286681 天前
ElasticSearch入门
大数据·elasticsearch·搜索引擎