FEATURE: add advanced order to search (#10385)
Similar to `advanced_filter` I introduced `advanced_order`. I needed a new option because default orders are evaluated after advanced_filter so I couldn't use it. Also, that part is a little bit more generic ``` elsif word =~ /order:\w+/ @order = word.gsub('order:', '').to_sym nil ``` After those changes, I can use them in plugins in this way: ``` Search.advanced_order(:votes) do |posts| posts.reorder("COALESCE((SELECT dvvc.counter FROM discourse_voting_vote_counters dvvc WHERE dvvc.topic_id = subquery.topic_id), 0) DESC") end ```
This commit is contained in:
parent
ab2b6f8dea
commit
12a00d6dc5
|
@ -190,6 +190,22 @@ class Plugin::Instance
|
|||
DiscoursePluginRegistry.register_editable_group_custom_field(field, self)
|
||||
end
|
||||
|
||||
# Allows to define custom search order. Example usage:
|
||||
# Search.advanced_order(:chars) do |posts|
|
||||
# posts.reorder("(SELECT LENGTH(raw) FROM posts WHERE posts.topic_id = subquery.topic_id) DESC")
|
||||
# end
|
||||
def register_search_advanced_order(trigger, &block)
|
||||
Search.advanced_order(trigger, &block)
|
||||
end
|
||||
|
||||
# Allows to define custom search filters. Example usage:
|
||||
# Search.advanced_filter(/^min_chars:(\d+)$/) do |posts, match|
|
||||
# posts.where("(SELECT LENGTH(p2.raw) FROM posts p2 WHERE p2.id = posts.id) >= ?", match.to_i)
|
||||
# end
|
||||
def register_search_advanced_filter(trigger, &block)
|
||||
Search.advanced_filter(trigger, &block)
|
||||
end
|
||||
|
||||
# Request a new size for topic thumbnails
|
||||
# Will respect plugin enabled setting is enabled
|
||||
# Size should be an array with two elements [max_width, max_height]
|
||||
|
|
|
@ -277,6 +277,14 @@ class Search
|
|||
@results
|
||||
end
|
||||
|
||||
def self.advanced_order(trigger, &block)
|
||||
(@advanced_orders ||= {})[trigger] = block
|
||||
end
|
||||
|
||||
def self.advanced_orders
|
||||
@advanced_orders
|
||||
end
|
||||
|
||||
def self.advanced_filter(trigger, &block)
|
||||
(@advanced_filters ||= {})[trigger] = block
|
||||
end
|
||||
|
@ -659,11 +667,11 @@ class Search
|
|||
end
|
||||
end
|
||||
|
||||
if word == 'order:latest' || word == 'l'
|
||||
if word == 'l'
|
||||
@order = :latest
|
||||
nil
|
||||
elsif word == 'order:latest_topic'
|
||||
@order = :latest_topic
|
||||
elsif word =~ /order:\w+/
|
||||
@order = word.gsub('order:', '').to_sym
|
||||
nil
|
||||
elsif word == 'in:title' || word == 't'
|
||||
@in_title = true
|
||||
|
@ -677,12 +685,6 @@ class Search
|
|||
end
|
||||
end
|
||||
nil
|
||||
elsif word == 'order:views'
|
||||
@order = :views
|
||||
nil
|
||||
elsif word == 'order:likes'
|
||||
@order = :likes
|
||||
nil
|
||||
elsif word == 'in:all'
|
||||
@search_all_topics = true
|
||||
nil
|
||||
|
@ -1011,6 +1013,11 @@ class Search
|
|||
posts = aggregate_relation.from(posts)
|
||||
end
|
||||
|
||||
if @order
|
||||
advanced_order = Search.advanced_orders&.fetch(@order, nil)
|
||||
posts = advanced_order.call(posts) if advanced_order
|
||||
end
|
||||
|
||||
posts = posts.offset(offset)
|
||||
posts.limit(limit)
|
||||
end
|
||||
|
|
|
@ -1690,4 +1690,24 @@ describe Search do
|
|||
end
|
||||
end
|
||||
|
||||
context 'plugin extensions' do
|
||||
let!(:post0) { Fabricate(:post, raw: 'this is the first post about advanced filter with length more than 50 chars') }
|
||||
let!(:post1) { Fabricate(:post, raw: 'this is the second post about advanced filter') }
|
||||
|
||||
it 'allows to define custom filter' do
|
||||
expect(Search.new("advanced").execute.posts).to eq([post1, post0])
|
||||
Search.advanced_filter(/^min_chars:(\d+)$/) do |posts, match|
|
||||
posts.where("(SELECT LENGTH(p2.raw) FROM posts p2 WHERE p2.id = posts.id) >= ?", match.to_i)
|
||||
end
|
||||
expect(Search.new("advanced min_chars:50").execute.posts).to eq([post0])
|
||||
end
|
||||
|
||||
it 'allows to define custom order' do
|
||||
expect(Search.new("advanced").execute.posts).to eq([post1, post0])
|
||||
Search.advanced_order(:chars) do |posts|
|
||||
posts.reorder("(SELECT LENGTH(raw) FROM posts WHERE posts.topic_id = subquery.topic_id) DESC")
|
||||
end
|
||||
expect(Search.new("advanced order:chars").execute.posts).to eq([post0, post1])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue