Haystack+ES解決搜索服務


  最近項目組需要對老的搜索項目進行遷移和改造,剛入職2個星期的我光榮的接受了這份工作,這也是我第一次接觸Haystack和Elasticsearch,以下是記錄下工作中的一些需求解決,具體haystack的玩法大家可以看查看官方文檔:https://django-haystack.readthedocs.io/en/master/,查看本文默認你已經基本了解了haystack的使用,包括基本的配置和使用

       在開始之前,我還是有必要灌輸幾個概念:什么是ES,什么是Haystack,兩者關系。

       1.什么是ES?

       在本文你只需要知道它是一個搜索服務器,存放着我們需要被搜索的數據,存儲結構類似於我們的數據庫,也可以對其記錄進行curd的操作,重要的是能夠進行‘分詞’,同樣是建立索引,數據庫則需要把整個一句話作為索引,然后才能通過查詢這一句話才能使用索引找到該記錄,而ES通過‘分詞’建立索引,可以建立多個單詞索引指向同一記錄,我們可以簡單的鍵入一兩個關鍵字就能調用索引彈出相關的信息,當然如果數據量少,就沒必要使用ES了,畢竟這種情況下使用模糊查詢也慢不了多少。

       2.什么是Haystack?

       Haystack 是以django的一個應用庫,主要用來整合市場是的幾大搜索后端作為django對它們操作的統一入口。

  3.兩者關系?

  Haystack通過封裝了各大搜索后端在python的操作庫,如ES就是elasticsearch,讓我們更專注於業務代碼,不需要關注ES和python,django的對接。

  實戰需求一: 當我在表中更新了數據,我需要手動更新ES的索引

       Haystack提供了 rebuild_index 和 update_index 兩種方法 在你安裝了haystack后 類似於這樣使用: python manager.py rebuild_index(你必須配置好了haystack在django) ,分別是重建和更新。兩者都是從數據庫表中同步到ES服務器,中間人就是django-Haystack,所以這兩者性能用起來非常差,並不是說update比rebuild一定要快很多,更新的原理就是刪除原記錄將新的記錄再插入一邊到ES中,所以在更新索引時因為ES中索引數目大時,更新無異於rebuild。慶幸的是update_index 可以傳入參數 age=x ,以某個時間字段的距離現在x小時內的記錄進行更新.search_index.py文件具體設置見下圖

       

       設置好后,我們需要實現一個手動執行update_index的方法,這里使用django的call_command

       

     實戰需求二: 我手動更新是增量的時候上述是沒什么問題的,現在我要做已有內容的變更

     這個需求到我手上時,有過兩種方案:

     方案一: 找到進行差異更新的那條索引記錄,使用最新的數據覆蓋。

  這個方案在我翻遍了Haystack的文檔后,四處找資料后,我放棄了,Haystack並沒有提供這樣的方法來更新某一條數據,更新並插入的動作。

   方案二: 刪掉舊數據,新增新數據。

       這個方案最終拿上了台面,原因,新增新數據這一步其實在上面已經完成,我們只需要找到舊數據的刪掉就行。

       就如何找到舊數據這點事最頭疼的,對於剛學會Haystack應用層使用的我來說,我知道Haystack使用 elasticsearch庫萊操作ES服務器,那具體如何操作,其實還是不清楚,我能知道的就是,在search_index里我們指定了model和檢索字段名,然后一頓配置后,為我們在ES中配置了和數據庫相同記錄數的記錄 ,但這些索引記錄和數據庫具體記錄是如何對應得我們不得而知,於是開始翻找源碼查看。

       幾經搜索,我們在每次更新索引的方法下面找到了這行代碼:

       這就是Haystack操作 python-elasticsearch進行批量插入記錄的方法

      

      分析一下每個參數: self.conn 可以猜到是一個ES的操作對象,index 則是我們建立的索引庫 類似於數據庫,doc_type則是類似於表的存在,默認全是modelresult request_timeout=30,這個應該是沒有的,我在往ES服務器重建4萬條數據是發現總是會在3萬多條報request timeout 所以我在這里改了默認值為30。

      主要就是prepped_docs,這個參數,你可以這么理解,這就是我們要插入的數據,但是有點不同的是,但是她包括了表的列名,也就是每一條記錄都有相同的一部分,就是key值,這就類似於我們的json格式 在python-elasticsearch 是這么玩的:

     

    一定包含的四個字段是 “_index,_type,_id,_source”

    現在我們已經找到了索引在ES保存的數據結構,我們只要找到每一條記錄的唯一值,然后刪除就行了,目前看起來 唯一值就是_id,確實就是。

    這個id的定義方式經過一番尋找:

   

 注釋非常明了,如果沒有被覆蓋,使用: app名字.model名字.pk(也就是model里的id)  到此我們已經知道了這個id的定義方式,接下來我們就找到一個刪除方法刪除這條記錄就行了

   但是很遺憾,Haystack並沒有這種單獨的刪除方法,所以我們只能通過操作最底層的 python-elasticsearch的刪除方法:

   

   到此,整個流程算是完了,

   綜上刪除索引的代碼就是以下兩行,主要是找到這個id

es = Elasticsearch([host])
es.delete(index='設置的index_name', doc_type='modelresult', id=id)

純原創,轉載注明來源

   

 

 

 

     

 

 

  

 

 

       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM