sunspot solr как правильно искать несколько моделей? Все примеры онлайн провалились

Как правильно искать несколько моделей в SunSpot Solr?

Модель профиля

has_one :match

searchable do
  string        :country
  string        :state
  string        :city
end

Модель спички

belongs_to :profile

searchable do
  string :looking_for_education
  integer :age_from
  integer :age_to
end

ProfilesController#Index

def index

  @search = Sunspot.search Profile, Match do

    with(:country, params[:country])
    with(:state,   params[:state])      
    with(:looking_for_education, params[:looking_for_education]) <= from the 2nd model
  end

  @profiles = @search.results

end

Это не с:

 Using a with statement like 
  with(:age).between(params[:age_from]..params[:age_to])
 undefined method `gsub' for nil:NilClass

Удаление
с (:age).between(params[:age_from]..params[:age_to]) затем пытается

Затем он пытается загрузить

view app/views/educators/educator.html.haml 

который не существует (я только использую

/app/views/profiles/_profile.html.haml 

показывать профили

РЕДАКТИРОВАНИЕ № 1:

Каковы хорошие проекты с открытым исходным кодом в ruby ​​на рельсах, которые используют sunspot и solr немного более продвинутым способом, чтобы взглянуть на них? Может быть, я смогу найти ответ там. Любой ответ в этом направлении также будет принят за вознаграждение, если оно приведет к возникновению этой проблемы, спасибо!

4 ответа

Решение

Метод поиска нескольких моделей правильный. Однако, похоже, что смысл вашего поиска не в том, что вы хотели. Похоже, вы пытаетесь сказать:

Дай мне все Profile записи с этими country а также state ценности и чьи Match запись имеет это looking_for_education значение

Ваш поиск, однако, говорит:

Дайте мне все записи типа Profile или же Match которые имеют все это country, state а также looking_for_education ценности

Потому что ни Profile ни Match иметь все эти поля в соответствующих searchable блоки, ни одна запись не может соответствовать указанным вами условиям.

Если я прав относительно вашего предполагаемого поведения, указанного выше, то вам нужно включить информацию о профиле, связанную с соответствием, в профиль searchable блок, вот так:

class Profile < ActiveRecord::Base
  has_one :match

  searchable do
    string(:country)
    string(:state)
    string(:city)
    string(:looking_for_education) { match.looking_for_education }
    integer(:age_from)             { match.age_from              }
    integer(:age_to)               { match.age_to                }
  end
end

Здесь мы сказали Sunspot индексировать свойства сопоставления соответствия профиля, как если бы они жили в самом профиле. В соответствующих блоках мы рассказали Sunspot, как заполнять эти значения при индексировании профиля.

Это позволит вам написать свой поиск, используя только Profile модель:

def index
  @search = Sunspot.search Profile do
    with(:country, params[:country])
    with(:state,   params[:state])      
    with(:looking_for_education, params[:looking_for_education])
    with(:age).between(params[:age_from]..params[:age_to])
  end

  @profiles = @search.results
end

Этот поиск вернет только Profile записи, в то же время отражая свойства сопоставления совпадений каждого профиля, потому что мы сохранили их, когда профиль был проиндексирован.

Обратите внимание, что это увеличивает сложность при индексировании ваших моделей. Если Match Записывая изменения, соответствующий профиль теперь необходимо переиндексировать, чтобы отразить эти изменения.

@moises-zaragoza правильно ответили на ваш вопрос, но у вас больше проблем, чем вы думаете, с тем, что вы хотите сделать.

Первая ошибка:

 Using a with statement like 
  with(:age).between(params[:age_from]..params[:age_to])
 undefined method `gsub' for nil:NilClass

Скорее всего, создается потому, что params[:age_from] и / или params[:age_to] равны нулю. Я не могу заверить это, потому что вы не показали трассировку стека. Вы можете исправить с помощью фильтра только тогда, когда они присутствуют: with(:age).between(params[:age_from]..params[:age_to]) if params[:age_from].present? и params[:age_to].present?

Вторая ошибка

Связанные с вашими взглядами. Я предполагаю, что вы визуализируете коллекцию или объект с помощью одного из помощников частичного объекта помощника rails, без указания частичного (опять же, без кода это более правильное предположение, чем что-либо еще):

<%= render @results %>

или же

<% @results.each do |result| %>
  <%= render result %>
<% end %>

Когда в Rails не указано частичное, оно угадывает частичное имя в зависимости от типа объекта. В этом случае, если ваш объект, например, класса Educator, который может быть подклассом Profile, Rails будет искать частичный файл educators/_educator.html.erb. Удостоверьтесь, что вы отрисовываете правильное частичное в зависимости от типа объекта, и это обеспечит вам то, что вы хотите.

Это то, что я делаю, когда мне приходится искать несколько моделей

Sunspot.search [Model1, Model2] do
  ....
end

Здесь ответ для поиска другой модели по соответствующей строке with

searchable(:auto_index => AppConfig.solr.auto_index) do
  string :category_name, :stored => true
  text :content, :stored => true
  text :title
  string :company_id, :stored => true
  time :published_on
end

search do |q|
  if params[:keyword].present?
    q.fulltext params[:keyword] do
      fields(:deal_data)
    end
  end
  if (ids = params["company_id"]).present?
    ids = ids.split(",")
    q.with(:company_id,ids) #here company id formate should be ["***","***"]
  end
end
Другие вопросы по тегам