forked from fedi/mastodon
Fix accounts search by full/partial display name and others (#11580)
- Restrict followers counts to local users to minimize local advantage - Fix emoji shortcodes causing error in search - Fix search syntax parse errors not being caught
This commit is contained in:
parent
6e872c6dab
commit
70da6d6630
|
@ -26,10 +26,17 @@ class AccountsIndex < Chewy::Index
|
||||||
define_type ::Account.searchable.includes(:account_stat), delete_if: ->(account) { account.destroyed? || !account.searchable? } do
|
define_type ::Account.searchable.includes(:account_stat), delete_if: ->(account) { account.destroyed? || !account.searchable? } do
|
||||||
root date_detection: false do
|
root date_detection: false do
|
||||||
field :id, type: 'long'
|
field :id, type: 'long'
|
||||||
field :display_name, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
|
||||||
field :acct, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content', value: ->(account) { [account.username, account.domain].compact.join('@') }
|
field :display_name, type: 'text', analyzer: 'content' do
|
||||||
field :following_count, type: 'long', value: ->(account) { account.active_relationships.count }
|
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
||||||
field :followers_count, type: 'long', value: ->(account) { account.passive_relationships.count }
|
end
|
||||||
|
|
||||||
|
field :acct, type: 'text', analyzer: 'content', value: ->(account) { [account.username, account.domain].compact.join('@') } do
|
||||||
|
field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'content'
|
||||||
|
end
|
||||||
|
|
||||||
|
field :following_count, type: 'long', value: ->(account) { account.following.local.count }
|
||||||
|
field :followers_count, type: 'long', value: ->(account) { account.followers.local.count }
|
||||||
field :last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at }
|
field :last_status_at, type: 'date', value: ->(account) { account.last_status_at || account.created_at }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class SearchQueryParser < Parslet::Parser
|
class SearchQueryParser < Parslet::Parser
|
||||||
rule(:term) { match('[^\s":]').repeat(1).as(:term) }
|
rule(:term) { match('[^\s":]').repeat(1).as(:term) }
|
||||||
rule(:quote) { str('"') }
|
rule(:quote) { str('"') }
|
||||||
rule(:colon) { str(':') }
|
rule(:colon) { str(':') }
|
||||||
rule(:space) { match('\s').repeat(1) }
|
rule(:space) { match('\s').repeat(1) }
|
||||||
rule(:operator) { (str('+') | str('-')).as(:operator) }
|
rule(:operator) { (str('+') | str('-')).as(:operator) }
|
||||||
rule(:prefix) { (term >> colon).as(:prefix) }
|
rule(:prefix) { (term >> colon).as(:prefix) }
|
||||||
rule(:phrase) { (quote >> (term >> space.maybe).repeat >> quote).as(:phrase) }
|
rule(:shortcode) { (colon >> term >> colon.maybe).as(:shortcode) }
|
||||||
rule(:clause) { (prefix.maybe >> operator.maybe >> (phrase | term)).as(:clause) }
|
rule(:phrase) { (quote >> (term >> space.maybe).repeat >> quote).as(:phrase) }
|
||||||
rule(:query) { (clause >> space.maybe).repeat.as(:query) }
|
rule(:clause) { (prefix.maybe >> operator.maybe >> (phrase | term | shortcode)).as(:clause) }
|
||||||
|
rule(:query) { (clause >> space.maybe).repeat.as(:query) }
|
||||||
root(:query)
|
root(:query)
|
||||||
end
|
end
|
||||||
|
|
|
@ -75,6 +75,8 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
|
|
||||||
if clause[:term]
|
if clause[:term]
|
||||||
TermClause.new(prefix, operator, clause[:term].to_s)
|
TermClause.new(prefix, operator, clause[:term].to_s)
|
||||||
|
elsif clause[:shortcode]
|
||||||
|
TermClause.new(prefix, operator, ":#{clause[:term]}:")
|
||||||
elsif clause[:phrase]
|
elsif clause[:phrase]
|
||||||
PhraseClause.new(prefix, operator, clause[:phrase].map { |p| p[:term].to_s }.join(' '))
|
PhraseClause.new(prefix, operator, clause[:phrase].map { |p| p[:term].to_s }.join(' '))
|
||||||
else
|
else
|
||||||
|
|
|
@ -67,7 +67,7 @@ class AccountSearchService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def from_elasticsearch
|
def from_elasticsearch
|
||||||
must_clauses = [{ multi_match: { query: terms_for_query, fields: likely_acct? ? %w(acct) : %w(acct^2 display_name), type: 'best_fields' } }]
|
must_clauses = [{ multi_match: { query: terms_for_query, fields: likely_acct? ? %w(acct.edge_ngram acct) : %w(acct.edge_ngram acct display_name.edge_ngram display_name), type: 'most_fields', operator: 'and' } }]
|
||||||
should_clauses = []
|
should_clauses = []
|
||||||
|
|
||||||
if account
|
if account
|
||||||
|
|
|
@ -52,7 +52,7 @@ class SearchService < BaseService
|
||||||
preloaded_relations = relations_map_for_account(@account, account_ids, account_domains)
|
preloaded_relations = relations_map_for_account(@account, account_ids, account_domains)
|
||||||
|
|
||||||
results.reject { |status| StatusFilter.new(status, @account, preloaded_relations).filtered? }
|
results.reject { |status| StatusFilter.new(status, @account, preloaded_relations).filtered? }
|
||||||
rescue Faraday::ConnectionFailed
|
rescue Faraday::ConnectionFailed, Parslet::ParseFailed
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue