使用Elasticsearch/Tire展平多态AR关系

Eri*_*rik 5 ruby-on-rails elasticsearch tire

我正在使用Rails 3应用程序,以允许人们申请资助等.我们使用Elasticsearch/Tire作为搜索引擎.

文件,例如赠款提案,由许多不同类型的答案组成,如联系信息或论文.在AR中,(通常是关系式dbs)你不能直接指定多态"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
Run Code Online (Sandbox Code Playgroud)

"有效负载"是个人答案类型的模型:联系人,叙述,多项选择等.(这些模型在"Answerable"下命名为.)

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
Run Code Online (Sandbox Code Playgroud)

从概念上讲,这个想法是一个答案,它由一个回答(函数,如连接表,存储所有答案共有的元数据)和一个回答(存储答案的实际内容)组成.这非常适合编写数据.搜索和检索,而不是.

我想使用Tire/ES来展示我的数据更理智的表示,以便进行搜索和阅读.在正常的轮胎设置中,我最终会得到(a)答案索引和(b)叙述,联系人,多种选择等的单独索引.相反,我想存储文档和答案,可能作为父/子.Answers索引将合并来自Answerings(id,question_id,updated_at ...)和Answerables(fname,lname,email ...)的数据.通过这种方式,我可以从单个索引中搜索Answers,按类型,question_id,document_id等进行过滤.更新将从Answering触发,但每次应答都会从其应答中提取信息.我正在使用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: root@me.com, narrative_content: "Back in the day, when I was a teenager, before I had...", answerable_type: "narrative" }
Run Code Online (Sandbox Code Playgroud)

所以,我有几个问题.

  1. 目标是为所有答案提供单一查询解决方案,而不管底层(可回答)类型.我以前从未设置过这样的东西.这看起来像是一个理智的问题吗?你能预见到我不能皱纹吗?替代方案/建议的/ etc.受欢迎的.
  2. 正如我所看到的,棘手的部分是映射.我的计划是在Answering模型中为需要索引选项的字段添加显式映射,然后让默认映射处理其余的:

    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
      [...]
    
    Run Code Online (Sandbox Code Playgroud)

    如果我没有为某个字段指定映射(例如"fname"),那么Tire/ES是否会依赖于动态映射?(我应该明确地映射将要使用的每个字段吗?)

提前致谢.如果我可以更具体,请告诉我.

t_i*_*chy 0

索引是解决这个问题的正确方法。除了索引字段名称之外,您还可以索引方法的结果。

mapping do
  indexes  :payload_details, :as => 'payload_details', :analyzer => 'snowball',:boost => 0
end

def payload_details
  "#{payload.fname} #{payload.lname}" #etc.
end
Run Code Online (Sandbox Code Playgroud)

索引值变成鸭子类型,因此如果您对视图中引用的所有值建立索引,则数据将可用。如果您访问未在索引项的模型上建立索引的属性,它将从 ActiveRecord 获取实例,如果您访问相关模型的属性,我很确定您会收到引用错误,但动态查找器可能会接管。