我正在将ElasticSearch与Tire一起使用来对一些ActiveRecord模型进行索引和搜索,并且我一直在寻找索引和搜索关联的“正确”方法。我还没有找到最佳解决方案,所以我想问问是否有人采用他们认为确实有效的方法。
作为一个示例设置(已完成,但说明了问题),假设我们有一本书,带有章节。每本书都有标题和作者,以及许多章节。每章都有文字。我们希望为书的字段和章节的文本建立索引,以便您可以按作者搜索书,也可以搜索其中包含某些单词的任何书。
class Book < ActiveRecord::Base include Tire::Model::Search include Tire::Model::Callbacks has_many :chapters mapping do indexes :title, :analyzer => 'snowball', :boost => 100 indexes :author, :analyzer => 'snowball' indexes :chapters, type: 'object', properties: { chapter_text: { type: 'string', analyzer: 'snowball' } } end end class Chapter < ActiveRecord::Base belongs_to :book end
因此,我使用以下命令进行搜索:
s = Book.search do query { string query_string } end
即使看起来索引应该执行此操作,这也不起作用。相反,如果我索引:
indexes :chapters, :as => 'chapters.map{|c| c.chapter_text}.join('|'), :analyzer => 'snowball'
这样可以使文本可搜索,但是显然这不是一个好办法,并且会丢失实际的关联对象。我已经尝试过各种搜索方式,例如:
s = Book.search do query do boolean do should { string query_string } should { string "chapters.chapter_text:#{query_string}" } end end end
那里也没有运气。如果有人有一个很好的,清晰的示例,就可以使用Tire索引和搜索关联的ActiveRecord对象,那么这似乎是对此处知识库的真正补充。
感谢您的任何想法和贡献。
Tire中对ActiveRecord关联的支持正在起作用,但是需要在应用程序内部进行一些调整。毫无疑问,图书馆应该在这里做得更好,将来肯定会做得更好。
就是说,这是一个可以在Elasticsearch中与Rails的关联一起工作的Tire配置的完整示例:active_record_associations.rb
让我在这里强调几件事。
首先,必须确保将关联的更改通知关联的父模型。
给定我们有一个Chapter模型“属于” a Book,我们需要做:
Chapter
Book
class Chapter < ActiveRecord::Base belongs_to :book, touch: true end
这样,当我们执行以下操作时:
book.chapters.create text: "Lorem ipsum...."
该book实例被通知增加的一章。
book
整理完这一部分后,我们需要将有关更改通知给 Tire ,并相应地更新elasticsearch索引:
class Book < ActiveRecord::Base has_many :chapters after_touch() { tire.update_index } end
(毫无疑问, Tire 应该after_touch自行拦截通知,而不是强迫您这样做。这是另一方面,证明了绕过图书馆的限制以不伤眼睛的方式进行工作有多么容易)
after_touch
尽管自述文件中提到您必须在Rails <3.1中禁用自动的“在JSON中添加根密钥”,但许多人还是忘记了它,因此您也必须在类定义中包括它:
self.include_root_in_json = false
现在是我们工作的重点-为我们的文档(模型)定义适当的映射:
mapping do indexes :title, type: 'string', boost: 10, analyzer: 'snowball' indexes :created_at, type: 'date' indexes :chapters do indexes :text, analyzer: 'snowball' end end
请注意,我们title使用created_at了相关模型的升序索引(作为“日期”)和章节文本。在Elasticsearch中,所有数据都有效地“归一化”为单个文档(如果这样的话会稍微有意义)。
title
created_at
作为最后一步,我们必须正确地序列化Elasticsearch索引中的文档。注意我们如何利用 ActiveRecord中 的便捷to_json方法: __
to_json
def to_indexed_json to_json( include: { chapters: { only: [:text] } } ) end
设置好所有这些设置之后,我们就可以在文档的Book和Chapter部分中搜索属性。
请运行开头链接的Ruby文件active_record_associations.rb,以查看完整图片。
有关更多信息,请参考以下资源: