百萬字文本數(shù)據(jù)存儲(chǔ)與搜索:Elasticsearch + Java客戶端實(shí)踐

2024-12-16 18:00 更新

大家好,我是 V 哥。在處理百萬字文本內(nèi)容搜索的場景中,使用 Elasticsearch 是一個(gè)非常合適的選擇。Elasticsearch 可以輕松處理大規(guī)模文本數(shù)據(jù),并提供全文搜索、模糊查詢、以及高效的搜索結(jié)果排序等功能。本文將提供一個(gè)詳細(xì)的 Java 代碼案例,展示如何將百萬字文本數(shù)據(jù)存儲(chǔ)到 Elasticsearch 中并實(shí)現(xiàn)高效搜索。

方案設(shè)計(jì)

  1. 數(shù)據(jù)導(dǎo)入:將百萬字的文本數(shù)據(jù)通過 Java 客戶端導(dǎo)入 Elasticsearch 索引。
  2. 全文檢索:使用 Elasticsearch 的全文檢索功能,支持高效地對(duì)大規(guī)模文本進(jìn)行搜索。
  3. 結(jié)果高亮顯示:將匹配的搜索關(guān)鍵詞進(jìn)行高亮顯示,方便用戶快速定位。

主要步驟

  1. Elasticsearch Java 客戶端配置
  2. 創(chuàng)建索引與映射
  3. 插入百萬字文本數(shù)據(jù)
  4. 實(shí)現(xiàn)全文檢索與高亮顯示

1. Elasticsearch Java 客戶端配置

首先,我們需要在 Java 項(xiàng)目中集成 Elasticsearch 客戶端。

Maven 依賴

pom.xml 文件中添加 Elasticsearch Java 客戶端的依賴:

  1. <dependencies>
  2. <!-- Elasticsearch Java Client -->
  3. <dependency>
  4. <groupId>org.elasticsearch.client</groupId>
  5. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  6. <version>7.10.2</version>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.apache.httpcomponents</groupId>
  10. <artifactId>httpclient</artifactId>
  11. <version>4.5.13</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>com.fasterxml.jackson.core</groupId>
  15. <artifactId>jackson-databind</artifactId>
  16. <version>2.11.3</version>
  17. </dependency>
  18. </dependencies>

創(chuàng)建 Elasticsearch 客戶端

  1. import org.elasticsearch.client.RestHighLevelClient;
  2. import org.elasticsearch.client.RestClient;
  3. import org.apache.http.HttpHost;
  4. public class ESClient {
  5. public static RestHighLevelClient createClient() {
  6. return new RestHighLevelClient(
  7. RestClient.builder(
  8. new HttpHost("localhost", 9200, "http")
  9. )
  10. );
  11. }
  12. }

在此例中,我們假設(shè) Elasticsearch 已經(jīng)在本地運(yùn)行,端口為 9200。

2. 創(chuàng)建索引與映射

我們需要?jiǎng)?chuàng)建一個(gè)索引來存儲(chǔ)文本數(shù)據(jù),并設(shè)置索引的映射(mapping)。可以為文本字段配置 text 類型,以支持全文搜索功能。

  1. import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
  2. import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
  3. import org.elasticsearch.client.RequestOptions;
  4. import org.elasticsearch.client.indices.CreateIndexRequest;
  5. import org.elasticsearch.client.indices.CreateIndexResponse;
  6. import org.elasticsearch.common.settings.Settings;
  7. import org.elasticsearch.common.xcontent.XContentType;
  8. public class ESIndexManager {
  9. public static void createTextIndex(RestHighLevelClient client) throws Exception {
  10. CreateIndexRequest request = new CreateIndexRequest("texts");
  11. request.settings(Settings.builder()
  12. .put("index.number_of_shards", 3) // 設(shè)置分片
  13. .put("index.number_of_replicas", 1) // 設(shè)置副本
  14. );
  15. String mapping = "{\n" +
  16. " \"properties\": {\n" +
  17. " \"title\": {\n" +
  18. " \"type\": \"text\"\n" +
  19. " },\n" +
  20. " \"content\": {\n" +
  21. " \"type\": \"text\",\n" +
  22. " \"analyzer\": \"standard\"\n" +
  23. " }\n" +
  24. " }\n" +
  25. "}";
  26. request.mapping(mapping, XContentType.JSON);
  27. CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
  28. if (createIndexResponse.isAcknowledged()) {
  29. System.out.println("Index created successfully.");
  30. } else {
  31. System.out.println("Index creation failed.");
  32. }
  33. }
  34. }

3. 插入百萬字文本數(shù)據(jù)

接下來,將百萬字的文本數(shù)據(jù)插入到 Elasticsearch 索引中。假設(shè)每篇文章由 titlecontent 組成。

  1. import org.elasticsearch.action.index.IndexRequest;
  2. import org.elasticsearch.action.index.IndexResponse;
  3. import org.elasticsearch.client.RequestOptions;
  4. import org.elasticsearch.common.xcontent.XContentFactory;
  5. public class ESDataManager {
  6. public static void indexDocument(RestHighLevelClient client, String title, String content) throws Exception {
  7. IndexRequest request = new IndexRequest("texts");
  8. request.source(XContentFactory.jsonBuilder()
  9. .startObject()
  10. .field("title", title)
  11. .field("content", content)
  12. .endObject()
  13. );
  14. IndexResponse response = client.index(request, RequestOptions.DEFAULT);
  15. System.out.println("Indexed document ID: " + response.getId());
  16. }
  17. public static void bulkInsert(RestHighLevelClient client, List<TextData> dataList) throws Exception {
  18. BulkRequest bulkRequest = new BulkRequest();
  19. for (TextData data : dataList) {
  20. IndexRequest request = new IndexRequest("texts");
  21. request.source(XContentFactory.jsonBuilder()
  22. .startObject()
  23. .field("title", data.getTitle())
  24. .field("content", data.getContent())
  25. .endObject()
  26. );
  27. bulkRequest.add(request);
  28. }
  29. client.bulk(bulkRequest, RequestOptions.DEFAULT);
  30. }
  31. }
  32. class TextData {
  33. private String title;
  34. private String content;
  35. // Constructors, getters and setters
  36. }

通過 bulkInsert 方法,可以一次性批量插入大量的文本數(shù)據(jù),這對(duì)于處理大規(guī)模數(shù)據(jù)非常高效。

4. 全文搜索與高亮顯示

當(dāng)文本數(shù)據(jù)插入完成后,我們就可以實(shí)現(xiàn)全文搜索。這里我們展示如何使用 match 查詢來搜索文本,并實(shí)現(xiàn)高亮顯示。

  1. import org.elasticsearch.action.search.SearchRequest;
  2. import org.elasticsearch.action.search.SearchResponse;
  3. import org.elasticsearch.client.RequestOptions;
  4. import org.elasticsearch.index.query.QueryBuilders;
  5. import org.elasticsearch.search.builder.SearchSourceBuilder;
  6. import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
  7. import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
  8. import org.elasticsearch.search.SearchHit;
  9. public class ESSearchManager {
  10. public static void searchWithHighlight(RestHighLevelClient client, String searchText) throws Exception {
  11. SearchRequest searchRequest = new SearchRequest("texts");
  12. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  13. // 構(gòu)建全文搜索的 query
  14. searchSourceBuilder.query(QueryBuilders.matchQuery("content", searchText));
  15. // 設(shè)置高亮顯示
  16. HighlightBuilder highlightBuilder = new HighlightBuilder();
  17. HighlightBuilder.Field highlightContent = new HighlightBuilder.Field("content");
  18. highlightContent.preTags("<em>").postTags("</em>");
  19. highlightBuilder.field(highlightContent);
  20. searchSourceBuilder.highlighter(highlightBuilder);
  21. searchRequest.source(searchSourceBuilder);
  22. // 執(zhí)行搜索
  23. SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
  24. // 解析搜索結(jié)果并高亮顯示
  25. for (SearchHit hit : searchResponse.getHits()) {
  26. String title = (String) hit.getSourceAsMap().get("title");
  27. String content = (String) hit.getSourceAsMap().get("content");
  28. System.out.println("Title: " + title);
  29. HighlightField highlight = hit.getHighlightFields().get("content");
  30. if (highlight != null) {
  31. String highlightedContent = String.join(" ", highlight.fragments());
  32. System.out.println("Highlighted Content: " + highlightedContent);
  33. } else {
  34. System.out.println("Content: " + content);
  35. }
  36. }
  37. }
  38. }

搜索示例

  1. public class Main {
  2. public static void main(String[] args) throws Exception {
  3. RestHighLevelClient client = ESClient.createClient();
  4. // 批量插入百萬字文本數(shù)據(jù)
  5. List<TextData> dataList = new ArrayList<>();
  6. dataList.add(new TextData("Title 1", "This is the first example of a long text content."));
  7. dataList.add(new TextData("Title 2", "Another document with interesting content to search."));
  8. ESDataManager.bulkInsert(client, dataList);
  9. // 全文搜索并高亮顯示
  10. ESSearchManager.searchWithHighlight(client, "content");
  11. // 關(guān)閉客戶端
  12. client.close();
  13. }
  14. }

5. 分析

  • 索引設(shè)計(jì):為全文搜索設(shè)置 text 字段類型,并使用標(biāo)準(zhǔn)分詞器進(jìn)行處理。對(duì)于大規(guī)模文本數(shù)據(jù),合理設(shè)置索引的分片數(shù)量(number_of_shards)和副本數(shù)量(number_of_replicas)以提高索引的性能。
  • 批量導(dǎo)入:在百萬字?jǐn)?shù)據(jù)量的情況下,使用 bulk 批量導(dǎo)入方式能極大提高插入效率。
  • 全文搜索:通過 matchQuery 對(duì)文本內(nèi)容進(jìn)行全文搜索,支持多種搜索方式如短語匹配、模糊查詢等。
  • 高亮顯示:通過 HighlightBuilder 實(shí)現(xiàn)對(duì)搜索結(jié)果中的匹配文本進(jìn)行高亮顯示,幫助用戶快速定位關(guān)鍵內(nèi)容。

6. 總結(jié)

通過 Elasticsearch 和 Java 客戶端,能夠高效地處理大規(guī)模文本數(shù)據(jù)的搜索需求。本文提供了從索引創(chuàng)建、數(shù)據(jù)插入到全文搜索和高亮顯示

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)