From df8f365d999e113615c51efee4cfa3115c267783 Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Tue, 7 Feb 2017 15:53:37 -0500 Subject: [PATCH] FEATURE: improve search so it searches sub categories by default If you want an exact category match use `category:=howto` or `#=howto" --- lib/search.rb | 40 ++++++++++++++++++++++++++++++---- spec/components/search_spec.rb | 21 +++++++++--------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/lib/search.rb b/lib/search.rb index cdad501bd86..187272e76a1 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -316,15 +316,32 @@ class Search end advanced_filter(/category:(.+)/) do |posts,match| - category_ids = Category.where('name ilike ? OR id = ? OR parent_category_id = ?', match, match.to_i, match.to_i).pluck(:id) + exact = false + + if match[0] == "=" + exact = true + match = match[1..-1] + end + + category_ids = Category.where('slug ilike ? OR name ilike ? OR id = ?', + match, match, match.to_i).pluck(:id) if category_ids.present? + + unless exact + category_ids += + Category.where('parent_category_id = ?', category_ids.first).pluck(:id) + end + posts.where("topics.category_id IN (?)", category_ids) else posts.where("1 = 0") end end - advanced_filter(/^\#([a-zA-Z0-9\-:]+)/) do |posts,match| + advanced_filter(/^\#([a-zA-Z0-9\-:=]+)/) do |posts,match| + + exact = true + slug = match.to_s.split(":") if slug[1] # sub category @@ -332,11 +349,26 @@ class Search category_id = Category.where(slug: slug[1].downcase, parent_category_id: parent_category_id).pluck(:id).first else # main category - category_id = Category.where(slug: slug[0].downcase, parent_category_id: nil).pluck(:id).first + if slug[0][0] == "=" + slug[0] = slug[0][1..-1] + else + exact = false + end + + category_id = Category.where(slug: slug[0].downcase) + .order('case when parent_category_id is null then 0 else 1 end') + .pluck(:id) + .first end if category_id - posts.where("topics.category_id = ?", category_id) + category_ids = [category_id] + + unless exact + category_ids += + Category.where('parent_category_id = ?', category_id).pluck(:id) + end + posts.where("topics.category_id IN (?)", category_ids) else posts.where("topics.id IN ( SELECT DISTINCT(tt.topic_id) diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb index a9184ef0906..5f1c2103375 100644 --- a/spec/components/search_spec.rb +++ b/spec/components/search_spec.rb @@ -580,21 +580,22 @@ describe Search do # main category category = Fabricate(:category, name: 'category 24', slug: 'category-24') topic = Fabricate(:topic, created_at: 3.months.ago, category: category) - post = Fabricate(:post, raw: 'hi this is a test 123', topic: topic) + post = Fabricate(:post, raw: 'Sams first post', topic: topic) - expect(Search.execute('this is a test #category-24').posts.length).to eq(1) - expect(Search.execute("this is a test category:#{category.id}").posts.length).to eq(1) - expect(Search.execute('this is a test #category-25').posts.length).to eq(0) + expect(Search.execute('sams post #category-24').posts.length).to eq(1) + expect(Search.execute("sams post category:#{category.id}").posts.length).to eq(1) + expect(Search.execute('sams post #category-25').posts.length).to eq(0) - # sub category sub_category = Fabricate(:category, name: 'sub category', slug: 'sub-category', parent_category_id: category.id) second_topic = Fabricate(:topic, created_at: 3.months.ago, category: sub_category) - Fabricate(:post, raw: 'hi testing again 123', topic: second_topic) + Fabricate(:post, raw: 'sams second post', topic: second_topic) - expect(Search.execute('testing again #category-24:sub-category').posts.length).to eq(1) - expect(Search.execute("testing again category:#{category.id}").posts.length).to eq(2) - expect(Search.execute("testing again category:#{sub_category.id}").posts.length).to eq(1) - expect(Search.execute('testing again #sub-category').posts.length).to eq(0) + expect(Search.execute("sams post category:category-24").posts.length).to eq(2) + expect(Search.execute("sams post category:=category-24").posts.length).to eq(1) + + expect(Search.execute("sams post #category-24").posts.length).to eq(2) + expect(Search.execute("sams post #=category-24").posts.length).to eq(1) + expect(Search.execute("sams post #sub-category").posts.length).to eq(1) # tags topic.tags = [Fabricate(:tag, name: 'alpha')]