题
我正在尝试实现基于SOLR的搜索消息线程。每条消息都可以有很多答复(答复只能是一个级别的深处。)。我想通过匹配搜索键的内容检索父邮件或与搜索键匹配的答复。
例如:
Hello Jack
Hello Janice
How are you?
..
I am Janice
How are you?
Welcome to the Jungle
Nothing better to do.
搜索 Janice
应该返回以下结果集:
Hello Jack # one of the child messages matches the key word
I am Janice # parent message matched the keyword)
我的模型如下:
class Message < ActiveRecord::Base
belongs_to :parent, :class_name => "Message"
has_many :replies, :class_name => "Message", :foreign_key => :parent_id
# content
searchable do
text :content
integer :parent_id
end
end
类似条件的嵌套子查询的DSL语法是什么?
编辑1
我考虑过创建一个用于持有所有索引的复合文本索引字段。但是,在我的情况下,这种方法是不可行的,因为我必须确保答复符合某些其他标准。
class Message < ActiveRecord::Base
belongs_to :parent, :class_name => "Message"
has_many :replies, :class_name => "Message", :foreign_key => :parent_id
belongs_to :category
# content
searchable do
text :content
integer :category_id
integer :parent_id
end
end
在上面的模型中,我想将文本搜索限制为给定类别。
解决方案
完成您要寻找的最佳方法是将答复内容以及您想搜索的任何其他字段的内容不利。
在黑子中,这很简单。您可能会在线研究的另一种常见情况是根据其评论的内容搜索博客文章。
在这里要注意的一件重要的事情:由于统计化,您需要一个 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
与父母不同。而且,要重新调查,您想与父母执行关键字匹配 或者 回复文本内容,您想按类别范围。
您有几个我看到的选择。我将从最简单的开始,然后描述一些可能的组合。最简单的方法是进行一个非常基本的搜索 - 不必担心否定性或任何一种 - 并通过ActivereCord关联重建您的亲子消息。
@search = Message.search do
keywords params[:q]
with(:category_id, params[:category_id])
end
@messages = @search.results
如您所见,范围 category_id
在黑子中很简单。这可能是您的大部分问题,我只是走了,使它比必须的要复杂得多:)
从那里,其中一些 @messages
将是父母,有些将是答复。当然,您的视野能够弄清哪个是哪个并相应地渲染的。
<% if message.parent %>
…
这里还有其他一些方法,具体取决于您的要求的确切性质。以上可能足够好,所以我不会在这里详细介绍它们。但是,如果您继续追求不合规化,则还可以为所有消息的答复中包含一个多值整数列。 category_id
s。就像是 integer :reply_category_ids, :multi => true
.
后一种方法将提供与整个消息线程的更宽松的匹配项,根据您的应用程序,这可能值得也不值得构成统计的复杂性。我将语法留给您,大部分是从我以前的示例中流动的。
如您所见,这里有一些排列,具体取决于您何时和在何处与该类别相对的位置。希望我上面的示例能够为您提供足够的能力,可以继续找出应用程序的确切细节。
其他提示
非常感谢,尼克,当我在所有表中使用任意的子弦启动全球搜索时,您的技巧帮助我解决了问题。就我而言,我必须使用FK检索父记录的属性,并在子表中搜索:
searchable do
...
text :ip_address, as: :ip_address_textp # nested searching
...
end
private
def ip_address
Address.find(address_id).ip # retrieve attribute from parent record with FK
end