Elasticsearch使用$ TERM頻率/逆文檔頻率算法,簡稱TF/IDF算法。
$ Term頻率(TF):搜索文本中的每個條目在字段文本中出現多少次?出現的次數越多,相關性越強。
如:搜索請求:hello world
妳好,世界很好
醫生2:妳好,妳好嗎
Doc1肯定比doc2高,因為hello world出現在doc1中。
逆文檔頻率(IDF):搜索文本中的每個條目在整個索引的所有文檔中出現的次數,出現的次數越多,相關度越低。
搜索請求:hello world
doc1:妳好,今天很好
醫生2:嗨,世界,妳好嗎
例如,索引中有10000個文檔,單詞hello在所有文檔中出現1000次。單詞world在所有文檔中出現了100次。
那麽最後的結果壹定是word得分更高。
關於_score還有壹個規律,ES。
字段長度規範:字段長度,字段越長,相關性越弱。
搜索請求:hello world
Doc 1: {"title": "hello文章"," content ":" Baba ABA 10000字" }
Doc 2: {"title": "myarticle "," content ":" blablabala 10000字,嗨世界" }
Hello world在整個索引中出現的次數相同。最終doc1得分較高。
搜索的時候,要依靠倒排索引;在排序時,需要依靠正字法索引來查看每個文檔的每個字段,然後進行排序。所謂正交索引,其實就是doc值,也可以用來進行排序、聚合、過濾等操作。Doc值保存在磁盤上。此時如果內存足夠,os會自動緩存在內存中,性能依然會很高。如果沒有足夠的內存,操作系統會將其寫入磁盤。
正交索引如下:
倒排索引不變性的好處
假設兩個文檔有相同值的時間戳字段,搜索結果按時間戳字段排序。由於搜索請求是在所有有效碎片化副本中輪詢的,因此當主碎片化處理請求出現時,這兩個文檔可能處於壹種順序,而副本碎片化處理請求處於另壹種順序。
這就是所謂的彈跳結果問題:用戶每次刷新頁面,搜索結果都以不同的順序出現。讓同壹個用戶壹直使用同壹個片段,可以避免這個問題。您可以將preference參數設置為特定的任意值,例如用戶會話ID。
諸如
如果妳想壹次找出比如654.38+萬條數據,性能會很差。這時候壹般會用scoll批量滾動查看,直到所有數據都查詢處理完畢。
Scoll,看起來像分頁,但使用場景其實是不壹樣的。分頁主要用於逐頁搜索,供用戶查看;Scoll主要用於批量檢索數據,供系統處理。
使用scoll滾動搜索,可以先搜索壹批數據,下次再搜索壹批數據,以此類推,直到搜索完所有數據。
Scoll search將在第壹次搜索時保存視圖的快照,然後只提供基於舊快照的數據搜索。如果在此期間數據發生變化,用戶將看不到。
基於_doc的排序方法具有較高的性能。
每次發送滾動請求時,我們還需要指定壹個scoll參數和壹個時間窗,每個搜索請求都可以在這個時間窗內完成。
獲得的結果將有壹個scoll_id,下次發送scoll請求時,您必須攜帶這個scoll _ ID。
1創建索引
2修改索引
3刪除索引
Lucene沒有類型的概念。在document中,type實際上是作為document的壹個字段存儲的,也就是_type,es通過_type對type進行過濾和篩選。
壹個索引中的多個類型實際上是存儲在壹起的,所以壹個索引下不能有多個同名的類型,類型或者其他設置也不壹樣,因為那是處理不了的。
例如
底層存儲是這樣的。
把結構相似的類型放在壹個索引下,這些類型應該有多個字段是相同的。
如果將這兩種類型的字段放在壹個索引下,那麽在底層的lucene中會有很多字段為空,並且會有嚴重的性能問題。
1,自定義動態策略
True:當遇到不熟悉的字段時,執行動態映射。
錯:忽略不熟悉的領域。
嚴格:遇到不熟悉的領域就報錯。
2.自定義您自己的動態映射模板(類型級別)。
以上設置是/my_index/my_type的字段。如果以_en結尾,會自動映射為字符串類型。
不能修改字段的設置。如果要修改壹個字段,要根據新的映射重新建立壹個索引,然後批量查詢數據,用bulk api重新寫入索引。
批量查詢時,建議采用scroll api,使用多線程並發檢索數據。每次scoll在指定日期查詢壹段數據,都可以交給壹個線程。
(1)壹開始是通過動態映射的方式插入數據,但是有些數據偶然是2017-01-01的日期格式,所以字段標題自動映射為日期類型,但實際上業務認為應該是字符串類型。
(2)稍後將字符串類型的標題值添加到索引時,會報錯。
(3)如果這個時候想修改標題的類型,那是不可能的。
(4)此時,唯壹的辦法就是重新建立索引,即重新建立壹個索引,查詢舊索引的數據,然後導入新索引。
(5)如果舊索引的名稱是old_index,而新索引的名稱是new_index,並且終端java應用已經在用old_index進行操作,那麽在重新啟動java應用之前,是否需要停止java應用,將使用的索引修改為new_index?在這個過程中,java應用程序會被關閉,可用性會降低。
(6)所以,給java壹個別名,指向舊索引。java應用先用,java應用先用goods_index別名操作。這時,它實際上指向舊的my_index。
(7)創建壹個新的索引,並將其標題類型調整為字符串。
(8)使用scroll api批量查詢數據。
(9) bulk api用於將scoll發現的壹批數據寫入新索引。
(10)反復循環8~9,查詢壹批又壹批數據,將每批數據寫入bulk api中的新索引。
(11)將goods_index別名切換為my_index_new,java應用將通過索引別名直接使用新索引中的數據。java應用程序不需要停止,它是高度可用的,無需提交。
(12)直接通過商品_索引別名查詢就可以了。
對於現有進程的問題,每次都要等fsync把段刷到磁盤裏,才能打開段進行搜索。在這種情況下,從編寫文檔到可以搜索到文檔可能需要1分鐘以上的時間!!!這不是壹個接近實時的搜索!!!主要瓶頸是fsync實際上是通過磁盤IO將數據寫入磁盤,非常耗時。