百万字文本内容搜索Java实现方案

大家好,我是 V 哥。在处理百万字文本内容搜索的场景中,使用 Elasticsearch 是一个非常合适的选择。Elasticsearch 可以轻松处理大规模文本数据,并提供全文搜索、模糊查询、以及高效的搜索结果排序等功能。本文将提供一个详细的 Java 代码案例,展示如何将百万字文本数据存储到 Elasticsearch 中并实现高效搜索。

方案设计

  1. 数据导入:将百万字的文本数据通过 Java 客户端导入 Elasticsearch 索引。
  2. 全文检索:使用 Elasticsearch 的全文检索功能,支持高效地对大规模文本进行搜索。
  3. 结果高亮显示:将匹配的搜索关键词进行高亮显示,方便用户快速定位。

主要步骤

  1. Elasticsearch Java 客户端配置
  2. 创建索引与映射
  3. 插入百万字文本数据
  4. 实现全文检索与高亮显示

1. Elasticsearch Java 客户端配置

首先,我们需要在 Java 项目中集成 Elasticsearch 客户端。

Maven 依赖

pom.xml 文件中添加 Elasticsearch Java 客户端的依赖:

xml 复制代码
<dependencies>
    <!-- Elasticsearch Java Client -->
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.10.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.11.3</version>
    </dependency>
</dependencies>
创建 Elasticsearch 客户端
java 复制代码
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.RestClient;
import org.apache.http.HttpHost;

public class ESClient {
    public static RestHighLevelClient createClient() {
        return new RestHighLevelClient(
            RestClient.builder(
                new HttpHost("localhost", 9200, "http")
            )
        );
    }
}

在此例中,我们假设 Elasticsearch 已经在本地运行,端口为 9200

2. 创建索引与映射

我们需要创建一个索引来存储文本数据,并设置索引的映射(mapping)。可以为文本字段配置 text 类型,以支持全文搜索功能。

java 复制代码
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;

public class ESIndexManager {
    public static void createTextIndex(RestHighLevelClient client) throws Exception {
        CreateIndexRequest request = new CreateIndexRequest("texts");
        request.settings(Settings.builder()
            .put("index.number_of_shards", 3) // 设置分片
            .put("index.number_of_replicas", 1) // 设置副本
        );

        String mapping = "{\n" +
                "  \"properties\": {\n" +
                "    \"title\": {\n" +
                "      \"type\": \"text\"\n" +
                "    },\n" +
                "    \"content\": {\n" +
                "      \"type\": \"text\",\n" +
                "      \"analyzer\": \"standard\"\n" +
                "    }\n" +
                "  }\n" +
                "}";

        request.mapping(mapping, XContentType.JSON);

        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        if (createIndexResponse.isAcknowledged()) {
            System.out.println("Index created successfully.");
        } else {
            System.out.println("Index creation failed.");
        }
    }
}

3. 插入百万字文本数据

接下来,将百万字的文本数据插入到 Elasticsearch 索引中。假设每篇文章由 titlecontent 组成。

java 复制代码
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.xcontent.XContentFactory;

public class ESDataManager {
    public static void indexDocument(RestHighLevelClient client, String title, String content) throws Exception {
        IndexRequest request = new IndexRequest("texts");

        request.source(XContentFactory.jsonBuilder()
            .startObject()
            .field("title", title)
            .field("content", content)
            .endObject()
        );

        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        System.out.println("Indexed document ID: " + response.getId());
    }

    public static void bulkInsert(RestHighLevelClient client, List<TextData> dataList) throws Exception {
        BulkRequest bulkRequest = new BulkRequest();
        for (TextData data : dataList) {
            IndexRequest request = new IndexRequest("texts");
            request.source(XContentFactory.jsonBuilder()
                .startObject()
                .field("title", data.getTitle())
                .field("content", data.getContent())
                .endObject()
            );
            bulkRequest.add(request);
        }
        client.bulk(bulkRequest, RequestOptions.DEFAULT);
    }
}

class TextData {
    private String title;
    private String content;
    
    // Constructors, getters and setters
}

通过 bulkInsert 方法,可以一次性批量插入大量的文本数据,这对于处理大规模数据非常高效。

4. 全文搜索与高亮显示

当文本数据插入完成后,我们就可以实现全文搜索。这里我们展示如何使用 match 查询来搜索文本,并实现高亮显示。

java 复制代码
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.SearchHit;

public class ESSearchManager {
    public static void searchWithHighlight(RestHighLevelClient client, String searchText) throws Exception {
        SearchRequest searchRequest = new SearchRequest("texts");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 构建全文搜索的 query
        searchSourceBuilder.query(QueryBuilders.matchQuery("content", searchText));

        // 设置高亮显示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        HighlightBuilder.Field highlightContent = new HighlightBuilder.Field("content");
        highlightContent.preTags("<em>").postTags("</em>");
        highlightBuilder.field(highlightContent);

        searchSourceBuilder.highlighter(highlightBuilder);
        searchRequest.source(searchSourceBuilder);

        // 执行搜索
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        // 解析搜索结果并高亮显示
        for (SearchHit hit : searchResponse.getHits()) {
            String title = (String) hit.getSourceAsMap().get("title");
            String content = (String) hit.getSourceAsMap().get("content");

            System.out.println("Title: " + title);
            HighlightField highlight = hit.getHighlightFields().get("content");
            if (highlight != null) {
                String highlightedContent = String.join(" ", highlight.fragments());
                System.out.println("Highlighted Content: " + highlightedContent);
            } else {
                System.out.println("Content: " + content);
            }
        }
    }
}
搜索示例
java 复制代码
public class Main {
    public static void main(String[] args) throws Exception {
        RestHighLevelClient client = ESClient.createClient();
        
        // 批量插入百万字文本数据
        List<TextData> dataList = new ArrayList<>();
        dataList.add(new TextData("Title 1", "This is the first example of a long text content."));
        dataList.add(new TextData("Title 2", "Another document with interesting content to search."));
        ESDataManager.bulkInsert(client, dataList);
        
        // 全文搜索并高亮显示
        ESSearchManager.searchWithHighlight(client, "content");
        
        // 关闭客户端
        client.close();
    }
}

5. 分析

  • 索引设计 :为全文搜索设置 text 字段类型,并使用标准分词器进行处理。对于大规模文本数据,合理设置索引的分片数量(number_of_shards)和副本数量(number_of_replicas)以提高索引的性能。
  • 批量导入 :在百万字数据量的情况下,使用 bulk 批量导入方式能极大提高插入效率。
  • 全文搜索 :通过 matchQuery 对文本内容进行全文搜索,支持多种搜索方式如短语匹配、模糊查询等。
  • 高亮显示 :通过 HighlightBuilder 实现对搜索结果中的匹配文本进行高亮显示,帮助用户快速定位关键内容。

6. 总结

通过 Elasticsearch 和 Java 客户端,能够高效地处理大规模文本数据的搜索需求。本文提供了从索引创建、数据插入到全文搜索和高亮显示

相关推荐
MSTcheng.2 分钟前
【C++】C++11新特性(二)
java·开发语言·c++·c++11
晓13135 分钟前
第七章 【C语言篇:文件】 文件全面解析
linux·c语言·开发语言
愚者游世5 分钟前
Delegating Constructor(委托构造函数)各版本异同
开发语言·c++·程序人生·面试·改行学it
一 乐6 分钟前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
KIKIiiiiiiii7 分钟前
微信个人号API二次开发中的解决经验
java·人工智能·python·微信
梵刹古音8 分钟前
【C语言】 指针基础与定义
c语言·开发语言·算法
80530单词突击赢8 分钟前
SpringBoot整合SpringMVC全解析
java·spring boot·后端
Ekehlaft11 分钟前
这款国产 AI,让 Python 小白也能玩转编程
开发语言·人工智能·python·ai·aipy
rit843249913 分钟前
MATLAB中Teager能量算子提取与解调信号的实现
开发语言·matlab
开源技术16 分钟前
Python GeoPandas基础知识:地图、投影和空间连接
开发语言·ide·python