Лучший способ выполнить то, что вы ищете, - это денормализовать содержимое ответов - и любые другие поля, которые вы хотите сделать доступными для поиска, - в их родительское Сообщение.
Это довольно просто сделать в Sunspot. Другой распространенный сценарий, который вы можете исследовать в Интернете, - это поиск сообщения в блоге на основе содержания его комментариев.
Здесь следует отметить одну важную вещь: из-за денормализации вам понадобится хук after_save
, чтобы ответы могли переиндексировать своего родителя при добавлении или обновлении.
В вашем случае изменения могут выглядеть примерно так ...
class Message < ActiveRecord::Base
# …
after_save :reindex_parent
searchable do
# …
text :replies_content
end
def replies_content
replies.collect(&:content).join(" ")
end
def reindex_parent
parent.solr_index!
end
end
(что text :replies_content
может также принять встроенный lambda
, если вы хотите сохранить несколько строк вместо определения нового метода. Это ваше дело.)
При таком подходе нет никаких реальных изменений в синтаксисе поиска, поскольку все содержимое ответов будет объединено с поиском по ключевым словам по умолчанию.
Если вы имеете в виду более конкретные случаи использования, вам нужно уточнить свой вопрос, но мне кажется, что это лучший и самый простой подход.
Последнее замечание: этот подход может быть немного сложным, если, например, ваши сообщения имеют много ответов. Вероятно, это хорошая идея, чтобы убедиться, что вы индексируете асинхронно, используя DelayedJob или Resque. Но это другой разговор.
Обновление 1: определение с определенным идентификатором category_id
Прежде всего, я предполагаю, что у каждого ответа может быть category_id
, отличный от его родителя. И, чтобы изменить состояние, вы хотите выполнить сопоставление ключевых слов с родительским или текстовым содержимым ответа, и вы хотите охватить по категориям.
У вас есть пара вариантов, которые я вижу. Я начну с самого простого, а затем опишу несколько вероятных комбинаций. Простейшим подходом было бы сделать довольно простой поиск - не беспокойтесь о денормализации или о чем-либо подобном - и реконструировать ваши родительско-дочерние сообщения с ассоциациями ActiveRecord.
@search = Message.search do
keywords params[:q]
with(:category_id, params[:category_id])
end
@messages = @search.results
Как видите, обзор по category_id
довольно прост в Sunspot. Может быть, это основная часть вашего вопроса, и я только что ушел и сделал его более сложным, чем должно быть:)
Оттуда некоторые из этих @messages
будут родителями, некоторые - ответами. Разумеется, в пределах вашей точки зрения вы можете определить, что есть что, и соответственно отобразить.
<% if message.parent %>
…
Здесь есть несколько других подходов в зависимости от точного характера ваших требований. Вышесказанное может быть достаточно хорошим, поэтому я не буду их здесь подробно описывать. Но если вы продолжите проводить денормализацию, вы также можете включить многозначный целочисленный столбец для всех ответов сообщения 'category_id
s. Что-то вроде integer :reply_category_ids, :multi => true
.
Этот последний подход обеспечит более слабые совпадения с потоком сообщений в целом, что может стоить или не стоить сложности денормализации в зависимости от вашего приложения. Я оставлю вам синтаксис, он в основном вытекает из моих предыдущих примеров.
Как видите, здесь есть несколько вариантов, в зависимости от того, когда и где вы хотите использовать эту категорию. Надеюсь, мои примеры приведут вас к тому, чтобы вы смогли понять точные особенности вашего приложения.