1. 程式人生 > >乾貨 | 知識庫全文檢索的最佳實踐

乾貨 | 知識庫全文檢索的最佳實踐

1、題記

這是stackoverflow上一篇精彩的問答。

原文不大好理解,我做了梳理+圖解;

原文是ES早期版本,部分寫法已不適用,所有DSL我在6.X上進行了重寫和驗證;

針對原文內容做了擴充套件。

2、知識庫全文檢索問題丟擲

重新審視一個停滯不前的專案,並尋求建議,對數千個“舊”文件進行現代化改造,

最終期望效果:通過網路訪問這些文件。
文件以各種格式存在,有些已經過時:
- .doc,
- PageMaker,
- 硬拷貝hardcopy (OCR),
- PDF

- ……

很多文件已經被轉化成掃描版的PDF,之前我們認為PDF型別是最終的文件格式,現在看來,我們想聽聽建議(比如:xml是不是更好呢?)

核心需求點:

1、一旦所有文件都採用通用格式,我們希望通過網頁介面提供其內容並提供搜尋服務。

2、我們希望通過搜尋,能夠靈活地只返回整個文件的部分頁面(我相信的Lucene / elasticsearch使這成為可能?!?)

3、如果所有文件是XML是否會更加靈活?

4、如何儲存、在哪裡儲存XML?是直接儲存在資料庫中還是儲存成檔案系統中的檔案?關於文件中的嵌入式影象/圖表呢?

以上,希望得到回覆。

註解:xml只是提問者的當時初步的理解。

3、精彩回覆

我將推薦ElasticSearch,我們先解決這個問題並討論如何實現它:

這有幾個部分:

  • 從文件中提取文字以使它們可以索引(indexable),以備檢索;
  • 以全文搜尋形式提供此文字;
  • 高亮顯示文件片段;
  • 知道文件中的哪些段落可用於分頁;
  • 返回完整的文件。

ElasticSearch可以提供什麼:

  • ElasticSearch(如Solr)使用Tika從各種文件格式中提取文字和元資料;
  • Elasticsearch提供了強大的全文搜尋功能。它可以配置為以適當的語言分析每個文件,它可以藉助boost提高某些欄位的權重(例如,標題比內容更重要),ngrams分詞等標準Lucene操作;
  • Elasticsearch可以高亮顯示搜尋結果;
  • Elasticsearch不知道這些片段在您的文件中出現的位置;
  • Elasticsearch可以將原始文件儲存為附件,也可以儲存並返回提取的文字。但它會返回整個文件,而不是一個頁面。

【直譯】您可以將整個文件作為附件傳送到ElasticSearch,並且可以進行全文搜尋。但是關鍵點在於上面的(4)和(5):知道你文件中的位置,並返回文件的某些部分。儲存單個頁面可能足以滿足您的“我在哪裡”的目的,但是您希望將它們分組,以便在搜尋結果中返回文件,即使搜尋關鍵字出現在不同的頁面上。

任務分解:

3.1、索引部分——將文件儲存在ElasticSearch中。

使用Tika(或任何你喜歡的)來從每個文件中提取文字。將其保留為純文字或HTML格式以保留一些格式。
(忘記XML,不需要它)。

每個文件提取元資料:標題,作者,章節,語言,日期等。

將原始文件儲存在您的檔案系統中,並記錄路徑,以便以後可以使用。

在ElasticSearch中,索引包含所有元資料和可能的章節列表的“doc”文件。

將每個頁面索引為“page”文件,其中包含:
- 包含“doc”文件ID的父欄位(請參閱下面的“父子關係”)
- 文字
- 頁碼
- 也許章節標題或編號
- 您想要搜尋的任何元資料

儲存必備——父子文件關係

通常,在ES(和大多數NoSQL解決方案)中,每個文件/物件都是獨立的 - 沒有真正的關係。

通過建立“doc”和“page”之間的父子關係,ElasticSearch確保子文件(即“頁面”)與父文件(“doc”)儲存在同一分片上。

這使您能夠執行has_child等的查詢方式,它將根據“page”的內容找到最匹配的“doc”。

圖解示例:
這裡寫圖片描述

二、檢索部分——
現在進行搜尋。

你如何做到這一點取決於你想如何展示你的結果

  • 按頁面page分組,
  • 按文件doc分組。

通過頁面的結果很容易。

此查詢返回匹配頁面的列表(每個頁面全部返回)以及頁面中高亮顯示的片段列表。

舉例如下:

POST /my_index/page/_search?pretty=1
{
   "query" : {
      "match" : {
         "text" : "interesting keywords"
      }
   },
     "highlight": {
    "pre_tags": [
      "<span style=\"color:red\">"
    ],
    "post_tags": [
      "</span>"
    ],
    "require_field_match": true,
    "fields": {
      "title": {}
    }
  }
   }

顯示包含文字高亮欄位的“doc”分組有點棘手。 它不能用一個單一的查詢來完成。

一種方法可能是:

第1步:通過對其子(“頁面”)查詢,返回最匹配的父級(“doc”)。

POST /my_index/doc/_search?pretty=1
{
  "query": {
    "has_child": {
      "type": "page",
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "text": "interesting keywords"
              }
            },
            {
              "term": {
                "type": "page"
              }
            },
            {
              "term": {
                "factor": "5"
              }
            }
          ]
        }
      },
      "score_mode": "sum"
    }
  }
}

第2步:從上述查詢中收集“doc”ID 發出新查詢,從匹配的“頁面”文件中獲取片段。

GET /my_index/page/_search?pretty=1
{
   "query" : {
      "bool" : {
        "must":{
         "query" : {
            "match" : {
               "text" : "interesting keywords"
            }
         }},
         "filter" : {
            "terms" : {
               "doc_id" : [1,2,3]
            }
         }
      }
   },
   "highlight" : {
      "fields" : {
         "text" : {}
      }
   }
}

第3步:在您的應用程式中,將上述查詢的結果按doc分組並顯示出來。

使用第二個查詢的搜尋結果,您已經擁有了可供顯示的頁面的全文。要轉到下一頁,您可以搜尋它:

GET /my_index/page/_search?pretty=1
{
   "query" : {
      "constant_score" : {
         "filter" : 
            [
               {
                  "term" : {
                     "doc_id" : 1
                  }
               },
               {
                  "term" : {
                     "page" : 2
                  }
               }
            ]
      }
   },
   "size" : 1
}

或者,給“頁面”文件提供一個由doc_id _ page_num(例如123_2)組成的ID,然後您可以通過如下的檢索獲取該頁面:

curl -XGET'http://127.0.0.1:9200/my_index/page/123_2

3、擴充套件

Tika是一個內容分析工具,自帶全面的parser工具類,能解析基本所有常見格式的檔案,得到檔案的metadata,content等內容,返回格式化資訊。總的來說可以作為一個通用的解析工具。特別對於搜尋引擎的資料抓去和處理步驟有重要意義。

Tika是Apache的Lucene專案下面的子專案,在lucene的應用中可以使用tika獲取大批量文件中的內容來建立索引,非常方便,也很容易使用。

Apache Tika toolkit可以自動檢測各種文件(如word,ppt,xml,csv,ppt等)的型別並抽取文件的元資料和文字內容。

Tika集成了現有的文件解析庫,並提供統一的介面,使針對不同型別的文件進行解析變得更簡單。Tika針對搜尋引擎索引、內容分析、轉化等非常有用。

4、有沒有現成的開源實現呢?

Ambar是一個開源文搜尋引擎,具有自動抓取,OCR識別,標籤分類和即時全文搜尋功能。

Ambar定義了在工作流程中實現全文字文件搜尋的新方法:

  • 輕鬆部署Ambar和一個單一的docker-compose檔案
  • 通過文件和影象內容執行類似Google的搜尋
  • Ambar支援所有流行的文件格式,如果需要的話可以執行OCR
  • 標記您的檔案
  • 使用簡單的REST
  • Api將Ambar整合到您的工作流程中

參考:

這裡寫圖片描述

2018-06-07 22:43 思於家中床前