Rails elasticsearch - name of the search area

I just go from the Tire jewel to the official elasticsearch Ruby wrapper and work on implementing the best search features.

I have a model InventoryItemand a model Store. Storehas_many :inventory_items. I have a model area in a store calledlocal

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

I want the search to return results from this area, so I tried: InventoryItem.local(user).search....but it searches the entire index, not the area. After some research, it seems the filter is a good way to achieve this, but I'm not sure how to implement it. I am open to other ways to achieve this. My ultimate goal is to find a subset of the model InventoryItembased on the location of the store.

+4
source share
2 answers

Another thing you can do is send the list of correct identifiers on the right to elastic so that they themselves filter the entries and then search for the remaining ones. We did not conduct tests, but still faster, but I think it is necessary, because elasticity is a search engine.

I will try to make an example using your classes + variables and our experience:

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

And the model:

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 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

So you also need to index store_id.

Read more about filters here .

+5
source

I will leave this answer without accepting until grandeur comes — feel free to add an answer if you think you have found the best solution that is lower.

.

:

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 records results. results , .. records AR, , , . ! docs.

0

All Articles