Я работаю с приложением Rails 3, чтобы люди могли подавать заявки на гранты и тому подобное. Мы используем Elasticsearch/Tire в качестве поисковой системы.
Документы, например заявки на гранты, состоят из множества ответов разных типов, таких как контактная информация или эссе. В AR (реляционные базы данных в целом) вы не можете напрямую указать полиморфное отношение has_many, поэтому вместо этого:
class Document < ActiveRecord::Base
has_many :answerings
end
class Answering < ActiveRecord::Base
belongs_to :document
belongs_to :question
belongs_to :payload, :polymorphic => true
end
«Полезная нагрузка» — это модели для отдельных типов ответов: контакты, повествования, множественный выбор и так далее. (Эти модели находятся в пространстве имен в разделе «Отвечает».)
class Answerable::Narrative < ActiveRecord::Base
has_one :answering, :as => :payload
validates_presence_of :narrative_content
end
class Answerable::Contact < ActiveRecord::Base
has_one :answering, :as => :payload
validates_presence_of :fname, :lname, :city, :state, :zip...
end
Концептуально идея заключается в том, что ответ состоит из ответа (функционирует как сводная таблица, хранит метаданные, общие для всех ответов) и ответа (в котором хранится фактическое содержание ответа). Это прекрасно работает. для записи данных. Поиск и поиск, не так уж и много.
Я хочу использовать Tire/ES, чтобы предоставить более разумное представление моих данных для поиска и чтения. В обычной настройке Tire я бы получил (а) индекс для ответов и (б) отдельные индексы для повествований, контактов, множественного выбора и так далее. Вместо этого я хотел бы просто хранить документы и ответы, возможно, как родитель/дочерний элемент. Индекс ответов будет объединять данные из ответов (id, question_id, updated_at...) и ответов (fname, lname, email...). Таким образом, я могу искать ответы в одном индексе, фильтровать по типу, question_id, document_id и т. д. Обновления будут запускаться из ответа, но каждый ответ затем будет извлекать информацию из своего ответа. Я использую RABL для шаблонизации входных данных поисковой системы, так что это достаточно просто.
Answering.find(123).to_indexed_json # let's say it's a narrative
=> { id: 123, question_id: 10, :document_id: 24, updated_at: ..., updated_by: [email protected], narrative_content: "Back in the day, when I was a teenager, before I had...", answerable_type: "narrative" }
Итак, у меня есть пара вопросов.
- Цель состоит в том, чтобы предоставить решение с одним запросом для всех ответов, независимо от базового (отвечающего) типа. Я никогда раньше не устанавливал ничего подобного. Кажется ли это разумным подходом к проблеме? Ты можешь предвидеть морщины, которых я не могу? Альтернативы/предложения/и т.д. приветствуются.
Самая сложная часть, на мой взгляд, это картографирование. Мой план состоит в том, чтобы поместить явные сопоставления в модель ответа для полей, которым нужны параметры индексации, и просто позволить сопоставлениям по умолчанию позаботиться обо всем остальном:
mapping do indexes :question_id, :index => :not_analyzed indexes :document_id, :index => :not_analyzed indexes :narrative_content, :analyzer => :snowball indexes :junk_collection_total, :index => :not_analyzed indexes :some_other_crazy_field, :index [...]
Если я не укажу сопоставление для некоторого поля (скажем, «fname»), вернется ли Tire/ES к динамическому сопоставлению? (Должен ли я явно отображать каждое поле, которое будет использоваться?)
Заранее спасибо. Пожалуйста, дайте мне знать, если я могу быть более конкретным.