Sto lavorando con un'applicazione Rails 3 per consentire alle persone di richiedere sovvenzioni e simili. Stiamo usando Elasticsearch/Tire come motore di ricerca.Appiattimento di una relazione AR polimorfa con Elasticsearch/Tyre
I documenti, ad esempio le proposte di sussidio, sono composti da molte risposte di tipi diversi, ad esempio informazioni di contatto o saggi. In AR, (DBS relazionali in generale) non è possibile specificare un polimorfica relazione "has_many" direttamente, così invece:
class Document < ActiveRecord::Base
has_many :answerings
end
class Answering < ActiveRecord::Base
belongs_to :document
belongs_to :question
belongs_to :payload, :polymorphic => true
end
"payload" sono modelli per i singoli tipi di risposta: Contatti, narrazioni, a scelta multipla, e presto. (Questi modelli sono namespace sotto "risponde.")
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
Concettualmente, l'idea è una risposta è composto da una segreteria (funzioni come un tavolo da unire, negozi di metadati comune a tutte le risposte) e un responsabile (che memorizza il contenuto effettivo della risposta). Funziona perfettamente per la scrittura di dati. Cerca e recupera, non tanto.
Voglio utilizzare Tyre/ES per esporre una rappresentazione più sana dei miei dati per la ricerca e la lettura. In una normale configurazione di Tyre, finirei con (a) un indice per le risposte e (b) indici separati per narrativa, contatti, scelte multiple e così via. Invece, mi piacerebbe solo archiviare documenti e risposte, possibilmente come genitore/figlio. L'indice Answers unirebbe i dati delle risposte (id, question_id, updated_at ...) e Answerables (fname, lname, email ...). In questo modo, posso cercare le risposte da un singolo indice, filtrare per tipo, question_id, id_documento, ecc. Gli aggiornamenti verranno attivati dalla risposta, ma ciascuna risposta inserirà quindi le informazioni dal suo answerable. Sto usando RABL per modellare gli input dei miei motori di ricerca, quindi è abbastanza facile.
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" }
Quindi, ho un paio di domande.
- L'obiettivo è fornire una soluzione a query singola per tutte le risposte, indipendentemente dal tipo (rispondente) sottostante. Non ho mai impostato qualcosa di simile prima. Questo sembra un approccio sano al problema? Puoi prevedere le rughe che non posso? Alternative/suggerimenti/etc. prego.
La parte difficile, come la vedo io, è la mappatura. Il mio piano è quello di mettere mapping espliciti nel modello di risposta per i campi che hanno bisogno di opzioni di indicizzazione, e lasciare che i mapping predefiniti prendersi cura di tutto il resto:
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 [...]
Se non si specifica una mappatura per qualche campo, (per esempio, "fname") Tire/ES riporterà la mappatura dinamica? (Dovrei mappare esplicitamente ogni campo che verrà utilizzato?)
Grazie in anticipo. Per favore fatemi sapere se posso essere più specifico.