FEATURE: search auto scopes on topic first
This commit is contained in:
parent
0438abf139
commit
2b10fdc97f
|
@ -828,6 +828,7 @@ en:
|
||||||
invitee_accepted: "%{display_username} accepted your invitation"
|
invitee_accepted: "%{display_username} accepted your invitation"
|
||||||
|
|
||||||
search:
|
search:
|
||||||
|
within_post: "#%{post_number} by %{username}: %{excerpt}"
|
||||||
types:
|
types:
|
||||||
category: 'Categories'
|
category: 'Categories'
|
||||||
topic: 'Topics'
|
topic: 'Topics'
|
||||||
|
|
|
@ -94,7 +94,7 @@ class Search
|
||||||
extra_posts = posts_query(expected_topics * Search.burst_factor)
|
extra_posts = posts_query(expected_topics * Search.burst_factor)
|
||||||
extra_posts = extra_posts.where("posts.topic_id NOT in (?)", @results.topic_ids) if @results.topic_ids.present?
|
extra_posts = extra_posts.where("posts.topic_id NOT in (?)", @results.topic_ids) if @results.topic_ids.present?
|
||||||
extra_posts.each do |p|
|
extra_posts.each do |p|
|
||||||
@results.add_result(SearchResult.from_post(p))
|
@results.add_result(SearchResult.from_post(p, @search_context, @term))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -162,6 +162,9 @@ class Search
|
||||||
elsif @search_context.is_a?(Category)
|
elsif @search_context.is_a?(Category)
|
||||||
# If the context is a category, restrict posts to that category
|
# If the context is a category, restrict posts to that category
|
||||||
posts = posts.order("CASE WHEN topics.category_id = #{@search_context.id} THEN 0 ELSE 1 END")
|
posts = posts.order("CASE WHEN topics.category_id = #{@search_context.id} THEN 0 ELSE 1 END")
|
||||||
|
elsif @search_context.is_a?(Topic)
|
||||||
|
posts = posts.order("CASE WHEN topics.id = #{@search_context.id} THEN 0 ELSE 1 END,
|
||||||
|
CASE WHEN topics.id = #{@search_context.id} THEN posts.post_number ELSE 999999 END")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -192,16 +195,20 @@ class Search
|
||||||
|
|
||||||
def topic_search
|
def topic_search
|
||||||
|
|
||||||
# If we have a user filter, search all posts by default with a higher limit
|
posts = if @search_context.is_a?(User)
|
||||||
posts = if @search_context.present? and @search_context.is_a?(User)
|
# If we have a user filter, search all posts by default with a higher limit
|
||||||
posts_query(@limit * Search.burst_factor)
|
posts_query(@limit * Search.burst_factor)
|
||||||
else
|
elsif @search_context.is_a?(Topic)
|
||||||
posts_query(@limit).where(post_number: 1)
|
posts_query(@limit).where('posts.post_number = 1 OR posts.topic_id = ?', @search_context.id)
|
||||||
end
|
else
|
||||||
|
posts_query(@limit).where(post_number: 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
posts.each do |p|
|
posts.each do |p|
|
||||||
@results.add_result(SearchResult.from_post(p))
|
@results.add_result(SearchResult.from_post(p, @search_context, @term))
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
class Search
|
class Search
|
||||||
|
|
||||||
class SearchResult
|
class SearchResult
|
||||||
|
class TextHelper
|
||||||
|
extend ActionView::Helpers::TextHelper
|
||||||
|
end
|
||||||
|
|
||||||
attr_accessor :type, :id
|
attr_accessor :type, :id
|
||||||
|
|
||||||
# Category attributes
|
# Category attributes
|
||||||
|
@ -36,14 +40,27 @@ class Search
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.from_topic(t)
|
def self.from_topic(t, custom_title=nil)
|
||||||
SearchResult.new(type: :topic, id: t.id, title: t.title, url: t.relative_url)
|
SearchResult.new(type: :topic, id: t.id, title: custom_title || t.title, url: t.relative_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.from_post(p)
|
def self.from_post(p, context, term)
|
||||||
|
custom_title =
|
||||||
|
if context && context.id == p.topic_id
|
||||||
|
excerpt = TextHelper.excerpt(p.raw, term.split(/\s+/)[0], radius: 30)
|
||||||
|
excerpt = TextHelper.truncate(p.raw, length: 50) if excerpt.blank?
|
||||||
|
I18n.t("search.within_post",
|
||||||
|
post_number: p.post_number,
|
||||||
|
username: p.user && p.user.username,
|
||||||
|
excerpt: excerpt
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
if p.post_number == 1
|
if p.post_number == 1
|
||||||
# we want the topic link when it's the OP
|
# we want the topic link when it's the OP
|
||||||
SearchResult.from_topic(p.topic)
|
SearchResult.from_topic(p.topic, custom_title)
|
||||||
|
elsif context && context.id == p.topic_id
|
||||||
|
SearchResult.new(type: :topic, id: "_#{p.id}", title: custom_title, url: p.url)
|
||||||
else
|
else
|
||||||
SearchResult.new(type: :topic, id: p.topic.id, title: p.topic.title, url: p.url)
|
SearchResult.new(type: :topic, id: p.topic.id, title: p.topic.title, url: p.url)
|
||||||
end
|
end
|
||||||
|
|
|
@ -125,6 +125,41 @@ describe Search do
|
||||||
context 'topics' do
|
context 'topics' do
|
||||||
let(:topic) { Fabricate(:topic) }
|
let(:topic) { Fabricate(:topic) }
|
||||||
|
|
||||||
|
|
||||||
|
context 'search within topic' do
|
||||||
|
|
||||||
|
def new_post(raw, topic)
|
||||||
|
Fabricate(:post, topic: topic, topic_id: topic.id, user: topic.user, raw: raw)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'displays multiple results within a topic' do
|
||||||
|
topic = Fabricate(:topic)
|
||||||
|
topic2 = Fabricate(:topic)
|
||||||
|
|
||||||
|
new_post('this is the other post I am posting', topic2)
|
||||||
|
post1 = new_post('this is the other post I am posting', topic)
|
||||||
|
post2 = new_post('this is my first post I am posting', topic)
|
||||||
|
post3 = new_post('this is a real long and complicated bla this is my second post I am Posting birds
|
||||||
|
with more stuff bla bla', topic)
|
||||||
|
post4 = new_post('this is my fourth post I am posting', topic)
|
||||||
|
new_post('this is my fifth post I am posting', topic2)
|
||||||
|
|
||||||
|
results = Search.new('posting', search_context: post1.topic).execute.find do |r|
|
||||||
|
r[:type] == "topic"
|
||||||
|
end[:results]
|
||||||
|
|
||||||
|
results.find{|r| r[:title].include? 'birds'}.should_not be_nil
|
||||||
|
|
||||||
|
results.map{|r| r[:id]}.should == [
|
||||||
|
post1.topic_id,
|
||||||
|
"_#{post2.id}",
|
||||||
|
"_#{post3.id}",
|
||||||
|
"_#{post4.id}",
|
||||||
|
topic2.id]
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'searching the OP' do
|
context 'searching the OP' do
|
||||||
let!(:post) { Fabricate(:post, topic: topic, user: topic.user) }
|
let!(:post) { Fabricate(:post, topic: topic, user: topic.user) }
|
||||||
let(:result) { first_of_type(Search.new('hello', type_filter: 'topic').execute, 'topic') }
|
let(:result) { first_of_type(Search.new('hello', type_filter: 'topic').execute, 'topic') }
|
||||||
|
|
Loading…
Reference in New Issue