mirror of
https://github.com/discourse/discourse.git
synced 2025-02-23 03:28:40 +08:00
FEATURE: add support for tag group search
The behaviour of #TERM in search has been amended 1. We try category or subcategory slugs 2. We try tags 3. We try tag-groups The term `hello #my-group` will search for all posts tagged with any of the tags in the tag group `My Group` Future work may be introducing a slug cache here or caching it in the table but the assumption is that the number of tag groups will not be huge
This commit is contained in:
parent
9a2eb5c8cb
commit
8f7a387aa7
@ -36,11 +36,18 @@ class TagGroup < ActiveRecord::Base
|
||||
@permissions = TagGroup.resolve_permissions(permissions)
|
||||
end
|
||||
|
||||
def self.resolve_permissions(permissions)
|
||||
everyone_group_id = Group::AUTO_GROUPS[:everyone]
|
||||
full = TagGroupPermission.permission_types[:full]
|
||||
# TODO: long term we can cache this if TONs of tag groups exist
|
||||
def self.find_id_by_slug(slug)
|
||||
self.pluck(:id, :name).each do |id, name|
|
||||
if Slug.for(name) == slug
|
||||
return id
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
mapped = permissions.map do |group, permission|
|
||||
def self.resolve_permissions(permissions)
|
||||
permissions.map do |group, permission|
|
||||
group_id = Group.group_id_from_param(group)
|
||||
permission = TagGroupPermission.permission_types[permission] unless permission.is_a?(Integer)
|
||||
[group_id, permission]
|
||||
|
@ -453,17 +453,34 @@ class Search
|
||||
# try a possible tag match
|
||||
tag_id = Tag.where_name(category_slug).pluck(:id).first
|
||||
if (tag_id)
|
||||
posts.where("topics.id IN (
|
||||
SELECT DISTINCT(tt.topic_id)
|
||||
FROM topic_tags tt
|
||||
WHERE tt.tag_id = ?
|
||||
)", tag_id)
|
||||
posts.where(<<~SQL, tag_id)
|
||||
topics.id IN (
|
||||
SELECT DISTINCT(tt.topic_id)
|
||||
FROM topic_tags tt
|
||||
WHERE tt.tag_id = ?
|
||||
)
|
||||
SQL
|
||||
else
|
||||
if tag_group_id = TagGroup.find_id_by_slug(category_slug)
|
||||
posts.where(<<~SQL, tag_group_id)
|
||||
topics.id IN (
|
||||
SELECT DISTINCT(tt.topic_id)
|
||||
FROM topic_tags tt
|
||||
WHERE tt.tag_id in (
|
||||
SELECT tag_id
|
||||
FROM tag_group_memberships
|
||||
WHERE tag_group_id = ?
|
||||
)
|
||||
)
|
||||
SQL
|
||||
|
||||
# a bit yucky but we got to add the term back in
|
||||
if match.to_s.length >= SiteSetting.min_search_term_length
|
||||
posts.where("posts.id IN (
|
||||
SELECT post_id FROM post_search_data pd1
|
||||
WHERE pd1.search_data @@ #{Search.ts_query(term: "##{match}")})")
|
||||
elsif match.to_s.length >= SiteSetting.min_search_term_length
|
||||
posts.where <<~SQL
|
||||
posts.id IN (
|
||||
SELECT post_id FROM post_search_data pd1
|
||||
WHERE pd1.search_data @@ #{Search.ts_query(term: "##{match}")})
|
||||
SQL
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1085,19 +1085,39 @@ describe Search do
|
||||
end
|
||||
|
||||
context 'tags' do
|
||||
let(:tag1) { Fabricate(:tag, name: 'lunch') }
|
||||
let(:tag2) { Fabricate(:tag, name: 'eggs') }
|
||||
let(:tag3) { Fabricate(:tag, name: 'sandwiches') }
|
||||
let(:topic1) { Fabricate(:topic, tags: [tag2, Fabricate(:tag)]) }
|
||||
let(:topic2) { Fabricate(:topic, tags: [tag2]) }
|
||||
let(:topic3) { Fabricate(:topic, tags: [tag1, tag2]) }
|
||||
let(:topic4) { Fabricate(:topic, tags: [tag1, tag2, tag3]) }
|
||||
let(:topic5) { Fabricate(:topic, tags: [tag2, tag3]) }
|
||||
let!(:post1) { Fabricate(:post, topic: topic1) }
|
||||
let!(:post2) { Fabricate(:post, topic: topic2) }
|
||||
let!(:post3) { Fabricate(:post, topic: topic3) }
|
||||
let!(:post4) { Fabricate(:post, topic: topic4) }
|
||||
let!(:post5) { Fabricate(:post, topic: topic5) }
|
||||
fab!(:tag1) { Fabricate(:tag, name: 'lunch') }
|
||||
fab!(:tag2) { Fabricate(:tag, name: 'eggs') }
|
||||
fab!(:tag3) { Fabricate(:tag, name: 'sandwiches') }
|
||||
|
||||
fab!(:tag_group) do
|
||||
group = TagGroup.create!(name: 'mid day')
|
||||
TagGroupMembership.create!(tag_id: tag1.id, tag_group_id: group.id)
|
||||
TagGroupMembership.create!(tag_id: tag3.id, tag_group_id: group.id)
|
||||
group
|
||||
end
|
||||
|
||||
fab!(:topic1) { Fabricate(:topic, tags: [tag2, Fabricate(:tag)]) }
|
||||
fab!(:topic2) { Fabricate(:topic, tags: [tag2]) }
|
||||
fab!(:topic3) { Fabricate(:topic, tags: [tag1, tag2]) }
|
||||
fab!(:topic4) { Fabricate(:topic, tags: [tag1, tag2, tag3]) }
|
||||
fab!(:topic5) { Fabricate(:topic, tags: [tag2, tag3]) }
|
||||
|
||||
def indexed_post(*args)
|
||||
SearchIndexer.enable
|
||||
Fabricate(:post, *args)
|
||||
end
|
||||
|
||||
fab!(:post1) { indexed_post(topic: topic1) }
|
||||
fab!(:post2) { indexed_post(topic: topic2) }
|
||||
fab!(:post3) { indexed_post(topic: topic3) }
|
||||
fab!(:post4) { indexed_post(topic: topic4) }
|
||||
fab!(:post5) { indexed_post(topic: topic5) }
|
||||
|
||||
it 'can find posts by tag group' do
|
||||
expect(Search.execute('#mid-day').posts.map(&:id)).to (
|
||||
contain_exactly(post3.id, post4.id, post5.id)
|
||||
)
|
||||
end
|
||||
|
||||
it 'can find posts with tag' do
|
||||
post4 = Fabricate(:post, topic: topic3, raw: "It probably doesn't help that they're green...")
|
||||
@ -1115,8 +1135,6 @@ describe Search do
|
||||
end
|
||||
|
||||
it 'can find posts with any tag from multiple tags' do
|
||||
Fabricate(:post)
|
||||
|
||||
expect(Search.execute('tags:eggs,lunch').posts.map(&:id).sort).to eq([post1.id, post2.id, post3.id, post4.id, post5.id].sort)
|
||||
end
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user