2014-09-23 29 views
4

我只是從輪胎寶石移動到官方elasticsearch Ruby wrapper,我正致力於實現更好的搜索功能。Rails彈性搜索命名示波器搜索

我有一個模型InventoryItem和模型StoreStore has_many :inventory_items。我有商店的模型範圍稱爲local

scope :local, lambda{|user| near([user.latitude, user.longitude], user.distance_preference, :order => :distance)} 

我希望搜索只從該範圍返回結果,所以我嘗試:InventoryItem.local(user).search....但它搜索整個索引,而不是範圍。在做了一些研究後,看起來過濾器是實現這一目標的好方法,但我不確定如何實施。我也願意以其他方式實現這一目標。我的最終目標是能夠根據商店位置搜索InventoryItem模型的子集。

回答

0

我會留下這個答案,直到賞金結束時才接受 - 如果您認爲自己找到了更好的解決方案,那麼可以自由添加答案。

這樣做的答案最終在挖掘後變得非常簡單。

使用命名範圍:

scope :for_stores, lambda{ |stores| where(store_id: stores.map(&:id)) } 

我控制器的方法:

def search 
    @stores = Store.local(current_user) # get local stores 
    response = InventoryItem.search 'whatever' # execute the search 
    @inventory_items = response.records.for_stores(@stores) # call records 
end 

在elasticsearch響應,您可以撥打recordsresults。調用results只會產生您可以顯示的索引結果等。調用records實際上會拉取AR記錄,從而允許您像上面那樣鏈接方法。涼!更多信息在docs明顯。

5

您可以做的另一件事是將有效ID的列表右鍵發送到彈性,因此它會自行過濾記錄,然後對剩下的記錄執行搜索。我們沒有進行測試,不管它是否更快,但我認爲它應該,因爲彈性畢竟是一個搜索引擎。

我會嘗試用你的類+變量和我們的經驗與組成一個例子:

def search 
    # retrieve ids you want to perform search within 
    @store_ids = Store.local(current_user).select(:id).pluck(:id) 
    # you could also check whether there are any ids available 
    # if there is none - no need to request elastic to search 
    @response = InventoryItem.search_by_store_ids('whatever', @store_ids) 
end 

和模型:

class InventoryItem 
    # ... 

    # search elastic only for passed store ids 
    def self.search_by_store_ids(query, store_ids, options = {})  
    # use method below 
    # also you can use it separately when you don't need any id filtering 
    self.search_all(query, options.deep_merge({ 
     query: { 
     filtered: { 
      filter: { 
      terms: { 
       store_id: store_ids 
      } 
      } 
     } 
     } 
    })) 
    end 

    # search elastic for all inventory items 
    def self.search_all(query, options = {}) 
    self.__elasticsearch__.search(
     { 
     query: { 
      filtered: { 
      query: { 
       # use your fields you want to search, our's was 'text' 
       match: { text: query }, 
      }, 
      filter: {}, 
      strategy: 'leap_frog_filter_first' # do the filter first 
      } 
     } 
     }.deep_merge(options) 
     # merge options from self.search_by_store_ids if calling from there 
     # so the ids filter will be applied 
    ) 
    end 
    # ... 
end 

這樣,你也得指數store_id

您可以閱讀更多關於過濾器here

+0

我還沒有測試過,但我同意它可以更快。我會獎勵賞金 - 謝謝你的詳細解答。我會測試這個,並在有機會時提供反饋。 – settheline 2014-10-05 23:18:17

+0

非常感謝!你的回答爲我提供了一個很好的模板,並且我終於能夠構建一個使用一組ID標識進行篩選的搜索(我無法在Rails上找到正確的方法,並且始終得到解析錯誤)。 – 2015-06-03 19:14:38

+0

這太棒了!我一直在尋找一種將範圍與elasticsearch結合起來的方法。 – 2016-11-09 06:02:25