ElasticSearch 高亮顯示大文檔搜索結果的策略和性能對比(譯)

2016年12月,咱們開始研究Ambar——一個文檔搜索系統。Ambar使用ElasticSearch做爲核心搜索引擎。html

在Ambar開發的過程當中,咱們處理了不少與ES相關的問題,咱們想分享咱們獲得的寶貴經驗。讓咱們從每一個搜索系統的一個重要功能開始——高亮顯示搜索結果。算法

在任何搜索系統的可用性中,適當的結果高亮顯示是最有價值的部分,首先,它爲用戶提供了關於內部搜索邏輯的必要信息,以及爲何顯示該結果。此外,它也使咱們可以僅僅經過快速瀏覽重點而不是下載和瀏覽整個文檔來估計結果。api

由於Ambar是一個文檔搜索系統,我說的文檔也是指文件,因此它必須處理很是大的文件(就全文搜索而言),大小大於100Mb。本文介紹了在利用ElasticSearch高亮顯示大型文檔時如何達到高性能。app

定義問題

Ambar使用ES做爲搜索引擎,搜索通過解析的文件/文檔內容及其元數據。下面是Ambar在ES中存儲一個文檔的例子:elasticsearch

{
    sha256: "1a4ad2c5469090928a318a4d9e4f3b21cf1451c7fdc602480e48678282ced02c",
    meta: [
        {
            id: "21264f64460498d2d3a7ab4e1d8550e4b58c0469744005cd226d431d7a5828d0",
            short_name: "quarter.pdf",
            full_name: "//winserver/store/reports/quarter.pdf",
            source_id: "crReports",
            extension: ".pdf",
            created_datetime: "2017-01-14 14:49:36.788",
            updated_datetime: "2017-01-14 14:49:37.140",
            extra: [],
            indexed_datetime: "2017-01-16 18:32:03.712"
        }
    ],
    content: {
        size: 112387192,
        indexed_datetime: "2017-01-16 18:32:33.321",
        author: "John Smith",
        processed_datetime: "2017-01-16 18:32:33.321",
        length: "",
        language: "",
        state: "processed",
        title: "Quarter Report (Q4Y2016)",
        type: "application/pdf",
        text: ".... laaaaaarge text here ...."
    }
}

上面的JSON文檔是一個解析後的.pdf文件,裏面有財務報告,文件大小約爲100Mb。content.text字段包含報告的解析文本,其大小也約爲100Mb。ide

讓咱們作一個簡單的實驗。索引1000個文檔,如我之前指定的文檔,而不定義任何索引調優或自定義映射。而後看看ES會多快地搜索它們,並高亮顯示content.text字段中的檢索關鍵字。性能

結果以下:測試

  • 在content.text字段中進行match_phrase搜索會耗費5-30秒
  • 突出顯示content.text字段中的文本內容,每次命中平均須要10秒

這種結果是不能接受的。任何使用搜索系統的用戶都但願在點擊「搜索」按鈕後當即獲得搜索結果,而不須要等待半分鐘就會出現第一個結果。讓咱們來看看高亮顯示這個緩慢突出的問題並解決它。ui

選擇高亮策略

ES 和 Lucene底層有三種高亮策略可供選擇,這是官方文檔連接,三種策略以下:搜索引擎

  • Plain - ES中默認的高亮顯示,它是最慢的,但它作了最精確的高亮顯示,幾乎徹底匹配Lucene的搜索邏輯。要高亮顯示檢索關鍵字,它必須將整個文檔加載到內存中並從新分析它。
  • Postings - 更快的一個。它將文檔的字段分割成句子,並使用BM25算法對匹配的結果進行標記,從而對結果進行排序,但它須要在索引中額外存儲句子的位置。
  • Fast Vector Highlighting (FVH) - 彷佛是最快的,特別是對於大型文檔。須要爲索引中的每一個令牌存儲位置偏移量。在本例中,要對檢索詞進行高亮顯示,它不須要檢索整個文檔,只需檢索接近命中的令牌,因爲每一個令牌的位置是已知的,所以這個速度很是快。

所以,如今你能夠猜到爲何ES能夠開箱即用地對大文檔中的檢索關鍵字高亮顯示。對於每次命中檢索整個文檔並從新分析它的性能很是昂貴,尤爲是對於大於1Mb的文檔。

因爲咱們絕對不能使用普通的高亮顯示方式,咱們測試了Postings和FVH。最後的選擇是FVH,緣由以下:

  • 若是使用FVH,一個100Mb的文檔高亮顯示大約須要10-20毫秒,Postings大約須要一秒鐘
  • Postings並不老是正確地將文檔的字段劃分爲句子,這就是爲何高亮顯示的大小會有很大的差別(在某些狀況下,從50個單詞到數千個單詞)。FVH沒有這種問題,由於它檢索固定數量的令牌,而不是句子。
  • Postings以任何順序突出顯示令牌,在複雜查詢中不能正常工做。對於引用,它不會正確地突出顯示具備指定slop值的match_phrase查詢的結果。它將把它解釋爲bool查詢,高亮顯示整個文檔字段中的每一個匹配令牌。

在FVH測試中,咱們發現了一個很是棘手的問題。它確實解釋了match_phrase查詢,而不是Lucene的搜索。它只按查詢中指定的順序突出顯示令牌,但Lucene的搜索將令牌按任意順序解釋爲命中。若是您正在搜索「John Smith」短語,可是文檔在其字段中有「Smith John」值,ES將檢索該文檔做爲命中結果,但FVH不會高亮顯示它。解決這個問題的辦法是短語置換。咱們提交不一樣的查詢以搜索和高亮顯示,Search獲取默認查詢,高亮顯示經過修改源短語中全部單詞位置的變化而構建查詢。

總結

ES實際上能夠處理大型文檔,而且仍然可以提供至關好的性能,重要的是正確地設置索引並記住全部與ES相關的問題。

編譯自:Highlighting Large Documents in ElasticSearch

相關文章
相關標籤/搜索