Add is:, has:, domain:, lang: search filters
This commit is contained in:
parent
26d465175a
commit
bf34294fcb
5 changed files with 52 additions and 5 deletions
|
@ -67,6 +67,10 @@ class StatusesIndex < Chewy::Index
|
||||||
field :account_id, type: 'long'
|
field :account_id, type: 'long'
|
||||||
field :created_at, type: 'date'
|
field :created_at, type: 'date'
|
||||||
field :visibility, type: 'keyword'
|
field :visibility, type: 'keyword'
|
||||||
|
field :domain, type: 'keyword', value: ->(status) { status.account.domain or Rails.configuration.x.local_domain }
|
||||||
|
field :lang, type: 'keyword', value: ->(status) { status.language }
|
||||||
|
field :is, type: 'keyword', value: ->(status) { status.searchable_is }
|
||||||
|
field :has, type: 'keyword', value: ->(status) { status.searchable_has }
|
||||||
|
|
||||||
field :text, type: 'text', value: ->(status) { status.searchable_text } do
|
field :text, type: 'text', value: ->(status) { status.searchable_text } do
|
||||||
field :stemmed, type: 'text', analyzer: 'content'
|
field :stemmed, type: 'text', analyzer: 'content'
|
||||||
|
|
|
@ -9,7 +9,7 @@ class SearchQueryParser < Parslet::Parser
|
||||||
rule(:prefix) { (term >> colon).as(:prefix) }
|
rule(:prefix) { (term >> colon).as(:prefix) }
|
||||||
rule(:shortcode) { (colon >> term >> colon.maybe).as(:shortcode) }
|
rule(:shortcode) { (colon >> term >> colon.maybe).as(:shortcode) }
|
||||||
rule(:phrase) { (quote >> (term >> space.maybe).repeat >> quote).as(:phrase) }
|
rule(:phrase) { (quote >> (term >> space.maybe).repeat >> quote).as(:phrase) }
|
||||||
rule(:clause) { (prefix.maybe >> operator.maybe >> (phrase | term | shortcode)).as(:clause) }
|
rule(:clause) { (operator.maybe >> prefix.maybe >> (phrase | term | shortcode)).as(:clause) }
|
||||||
rule(:query) { (clause >> space.maybe).repeat.as(:query) }
|
rule(:query) { (clause >> space.maybe).repeat.as(:query) }
|
||||||
root(:query)
|
root(:query)
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,6 +35,8 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
{ multi_match: { type: 'most_fields', query: clause.term, fields: ['text', 'text.stemmed'] } }
|
{ multi_match: { type: 'most_fields', query: clause.term, fields: ['text', 'text.stemmed'] } }
|
||||||
when PhraseClause
|
when PhraseClause
|
||||||
{ match_phrase: { text: { query: clause.phrase } } }
|
{ match_phrase: { text: { query: clause.phrase } } }
|
||||||
|
when PrefixClause
|
||||||
|
{ term: { clause.filter => clause.term } }
|
||||||
else
|
else
|
||||||
raise "Unexpected clause type: #{clause}"
|
raise "Unexpected clause type: #{clause}"
|
||||||
end
|
end
|
||||||
|
@ -99,10 +101,21 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
class PrefixClause
|
class PrefixClause
|
||||||
attr_reader :filter, :operator, :term, :order
|
attr_reader :filter, :operator, :term, :order
|
||||||
|
|
||||||
def initialize(prefix, term)
|
def initialize(prefix, operator, term)
|
||||||
case prefix
|
case operator
|
||||||
when 'from'
|
when '+', nil
|
||||||
@operator = :filter
|
@operator = :filter
|
||||||
|
when '-'
|
||||||
|
@operator = :must_not
|
||||||
|
else
|
||||||
|
raise "Unknown operator: #{str}"
|
||||||
|
end
|
||||||
|
|
||||||
|
case prefix
|
||||||
|
when 'domain', 'is', 'has', 'lang'
|
||||||
|
@filter = prefix.to_s
|
||||||
|
@term = term
|
||||||
|
when 'from'
|
||||||
@filter = :account_id
|
@filter = :account_id
|
||||||
|
|
||||||
username, domain = term.gsub(/\A@/, '').split('@')
|
username, domain = term.gsub(/\A@/, '').split('@')
|
||||||
|
@ -111,6 +124,8 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
|
|
||||||
@term = account.id
|
@term = account.id
|
||||||
when 'sort'
|
when 'sort'
|
||||||
|
raise Mastodon::SyntaxError unless operator.nil?
|
||||||
|
|
||||||
@operator = :order
|
@operator = :order
|
||||||
@term = :created_at
|
@term = :created_at
|
||||||
|
|
||||||
|
@ -133,7 +148,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
operator = clause[:operator]&.to_s
|
operator = clause[:operator]&.to_s
|
||||||
|
|
||||||
if clause[:prefix]
|
if clause[:prefix]
|
||||||
PrefixClause.new(prefix, clause[:term].to_s)
|
PrefixClause.new(prefix, operator, clause[:term].to_s)
|
||||||
elsif clause[:term]
|
elsif clause[:term]
|
||||||
TermClause.new(prefix, operator, clause[:term].to_s)
|
TermClause.new(prefix, operator, clause[:term].to_s)
|
||||||
elsif clause[:shortcode]
|
elsif clause[:shortcode]
|
||||||
|
|
|
@ -173,6 +173,26 @@ class Status < ApplicationRecord
|
||||||
].compact.join("\n\n")
|
].compact.join("\n\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def searchable_is
|
||||||
|
keywords = []
|
||||||
|
keywords << :bot if account.bot?
|
||||||
|
keywords << :local if local?
|
||||||
|
keywords << :local_only if local_only
|
||||||
|
keywords << :reply if reply?
|
||||||
|
keywords
|
||||||
|
end
|
||||||
|
|
||||||
|
def searchable_has
|
||||||
|
keywords = []
|
||||||
|
keywords << :cw if spoiler_text?
|
||||||
|
keywords << :link if FetchLinkCardService.new.link?(self)
|
||||||
|
keywords << :media if media_attachments.present?
|
||||||
|
keywords << :mention if mentions.present?
|
||||||
|
keywords << :poll if preloadable_poll.present?
|
||||||
|
keywords << :tag if tags.present?
|
||||||
|
keywords
|
||||||
|
end
|
||||||
|
|
||||||
def to_log_human_identifier
|
def to_log_human_identifier
|
||||||
account.acct
|
account.acct
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,6 +34,14 @@ class FetchLinkCardService < BaseService
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Borrow most of this machinery to detect whether the status has at least one link.
|
||||||
|
def link?(status)
|
||||||
|
@status = status
|
||||||
|
@original_url = parse_urls
|
||||||
|
!@original_url.nil?
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def process_url
|
def process_url
|
||||||
|
|
Loading…
Reference in a new issue