Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit b0e6971

Browse files
committed
add keyword search
1 parent bbeff5a commit b0e6971

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

lib/personas/tools/researcher.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def filter_description
3838
- tags (tag:tag1,tag2)
3939
- groups (group:group1,group2).
4040
- status (status:open, status:closed, status:archived, status:noreplies, status:single_user)
41+
- keywords (keywords:keyword1,keyword2) - specific words to search for in posts
4142
4243
If multiple tags or categories are specified, they are treated as OR conditions.
4344

lib/utils/research/filter.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,27 @@ def self.word_to_date(str)
8888
end
8989
end
9090

91+
register_filter(/\Akeywords?:(.*)\z/i) do |relation, keywords_param, _|
92+
if keywords_param.blank?
93+
relation
94+
else
95+
keywords = keywords_param.split(",").map(&:strip).reject(&:blank?)
96+
if keywords.empty?
97+
relation
98+
else
99+
# Build a ts_query string joined by | (OR)
100+
ts_query = keywords.map { |kw| kw.gsub(/['\\]/, " ") }.join(" | ")
101+
relation =
102+
relation.joins("JOIN post_search_data ON post_search_data.post_id = posts.id")
103+
relation.where(
104+
"post_search_data.search_data @@ to_tsquery(?, ?)",
105+
::Search.ts_config,
106+
ts_query,
107+
)
108+
end
109+
end
110+
end
111+
91112
register_filter(/\A(?:categories?|category):(.*)\z/i) do |relation, category_param, _|
92113
if category_param.include?(",")
93114
category_names = category_param.split(",").map(&:strip)

spec/lib/utils/research/filter_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,5 +91,47 @@
9191
expect(filter.search.pluck(:id)).to contain_exactly(feature_bug_post.id)
9292
end
9393
end
94+
95+
describe "full text keyword searching" do
96+
before_all { SearchIndexer.enable }
97+
fab!(:post_with_apples) do
98+
Fabricate(:post, raw: "This post contains apples", topic: feature_topic, user: user)
99+
end
100+
101+
fab!(:post_with_bananas) do
102+
Fabricate(:post, raw: "This post mentions bananas", topic: bug_topic, user: user)
103+
end
104+
105+
fab!(:post_with_both) do
106+
Fabricate(
107+
:post,
108+
raw: "This post has apples and bananas",
109+
topic: feature_bug_topic,
110+
user: user,
111+
)
112+
end
113+
114+
fab!(:post_with_none) do
115+
Fabricate(:post, raw: "No fruits here", topic: no_tag_topic, user: user)
116+
end
117+
118+
it "correctly filters posts by full text keywords" do
119+
filter = described_class.new("keywords:apples")
120+
expect(filter.search.pluck(:id)).to contain_exactly(post_with_apples.id, post_with_both.id)
121+
122+
filter = described_class.new("keywords:bananas")
123+
expect(filter.search.pluck(:id)).to contain_exactly(post_with_bananas.id, post_with_both.id)
124+
125+
filter = described_class.new("keywords:apples,bananas")
126+
expect(filter.search.pluck(:id)).to contain_exactly(
127+
post_with_apples.id,
128+
post_with_bananas.id,
129+
post_with_both.id,
130+
)
131+
132+
filter = described_class.new("keywords:oranges")
133+
expect(filter.search.count).to eq(0)
134+
end
135+
end
94136
end
95137
end

0 commit comments

Comments
 (0)