Fix ES setting for Account Full Text Search

This commit is contained in:
noellabo 2020-08-16 08:33:13 +09:00
parent 176dd499b7
commit 46d05ea6e8
3 changed files with 110 additions and 2 deletions

View file

@ -14,6 +14,8 @@ class AccountsIndex < Chewy::Index
},
sudachi_content: {
tokenizer: 'sudachi_tokenizer',
type: 'custom',
filter: %w(
lowercase
cjk_width
@ -22,8 +24,13 @@ class AccountsIndex < Chewy::Index
sudachi_baseform
search
),
tokenizer: 'sudachi_tokenizer',
},
},
normalizer: {
keyword: {
type: 'custom',
filter: %w(lowercase asciifolding cjk_width),
},
},
@ -33,6 +40,7 @@ class AccountsIndex < Chewy::Index
min_gram: 1,
max_gram: 15,
},
sudachi_tokenizer: {
type: 'sudachi_tokenizer',
discard_punctuation: true,
@ -61,12 +69,14 @@ class AccountsIndex < Chewy::Index
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
end
field :actor_type, type: 'keyword', analyzer: 'content'
field :actor_type, type: 'keyword', normalizer: 'keyword'
field :text, type: 'text', value: ->(account) { account.index_text } do
field :stemmed, type: 'text', analyzer: 'sudachi_content'
end
field :discoverable, type: 'boolean'
field :following_count, type: 'long', value: ->(account) { account.following.local.count }
field :followers_count, type: 'long', value: ->(account) { account.followers.local.count }
field :subscribing_count, type: 'long', value: ->(account) { account.subscribing.local.count }

54
app/lib/account_filter.rb Normal file
View file

@ -0,0 +1,54 @@
# frozen_string_literal: true
class AccountFilter
attr_reader :target_account, :account
def initialize(target_account, account, preloaded_relations = {})
@target_account = target_account
@account = account
@preloaded_relations = preloaded_relations
end
def filtered?
return false if !account.nil? && account.id == target_account.id
(account_present? && filtered_account?) || silenced_account?
end
private
def account_present?
!account.nil?
end
def filtered_account?
blocking_account? || blocked_by_account? || blocking_domain? || muting_account?
end
def blocking_account?
@preloaded_relations[:blocking] ? @preloaded_relations[:blocking][target_account.id] : account.blocking?(target_account)
end
def blocked_by_account?
@preloaded_relations[:blocked_by] ? @preloaded_relations[:blocked_by][target_account.id] : target_account.blocking?(account)
end
def blocking_domain?
@preloaded_relations[:domain_blocking_by_domain] ? @preloaded_relations[:domain_blocking_by_domain][target_account.domain] : account.domain_blocking?(target_account.domain)
end
def muting_account?
@preloaded_relations[:muting] ? @preloaded_relations[:muting][target_account.id] : account.muting?(target_account)
end
def silenced_account?
!account&.silenced? && target_account_silenced? && !account_following_target_account?
end
def target_account_silenced?
target_account.silenced?
end
def account_following_target_account?
@preloaded_relations[:following] ? @preloaded_relations[:following][target_account.id] : account&.following?(target_account)
end
end

View file

@ -0,0 +1,44 @@
# frozen_string_literal: true
class AccountFullTextSearchService < BaseService
def call(query, account, limit, options = {})
@query = query&.strip
@account = account
@options = options
@limit = limit.to_i
@offset = options[:offset].to_i
return if @query.blank? || @limit.zero?
perform_account_text_search!
end
private
def perform_account_text_search!
definition = parsed_query.apply(AccountsIndex.filter(term: { discoverable: true }))
results = definition.limit(@limit).offset(@offset).objects.compact
account_ids = results.map(&:id)
account_domains = results.map(&:domain).uniq.compact
preloaded_relations = relations_map_for_account(@account, account_ids, account_domains)
results.reject { |target_account| AccountFilter.new(target_account, @account, preloaded_relations).filtered? }
rescue Faraday::ConnectionFailed, Parslet::ParseFailed
[]
end
def relations_map_for_account(account, account_ids, domains)
{
blocking: Account.blocking_map(account_ids, account.id),
blocked_by: Account.blocked_by_map(account_ids, account.id),
muting: Account.muting_map(account_ids, account.id),
following: Account.following_map(account_ids, account.id),
domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, account.id),
}
end
def parsed_query
SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query))
end
end