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 :created_at, type: 'date' | ||||
|     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 :stemmed, type: 'text', analyzer: 'content' | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ class SearchQueryParser < Parslet::Parser | |||
|   rule(:prefix)    { (term >> colon).as(:prefix) } | ||||
|   rule(:shortcode) { (colon >> term >> colon.maybe).as(:shortcode) } | ||||
|   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) } | ||||
|   root(:query) | ||||
| end | ||||
|  |  | |||
|  | @ -35,6 +35,8 @@ class SearchQueryTransformer < Parslet::Transform | |||
|         { multi_match: { type: 'most_fields', query: clause.term, fields: ['text', 'text.stemmed'] } } | ||||
|       when PhraseClause | ||||
|         { match_phrase: { text: { query: clause.phrase } } } | ||||
|       when PrefixClause | ||||
|         { term: { clause.filter => clause.term } } | ||||
|       else | ||||
|         raise "Unexpected clause type: #{clause}" | ||||
|       end | ||||
|  | @ -99,10 +101,21 @@ class SearchQueryTransformer < Parslet::Transform | |||
|   class PrefixClause | ||||
|     attr_reader :filter, :operator, :term, :order | ||||
| 
 | ||||
|     def initialize(prefix, term) | ||||
|       case prefix | ||||
|       when 'from' | ||||
|     def initialize(prefix, operator, term) | ||||
|       case operator | ||||
|       when '+', nil | ||||
|         @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 | ||||
| 
 | ||||
|         username, domain = term.gsub(/\A@/, '').split('@') | ||||
|  | @ -111,6 +124,8 @@ class SearchQueryTransformer < Parslet::Transform | |||
| 
 | ||||
|         @term = account.id | ||||
|       when 'sort' | ||||
|         raise Mastodon::SyntaxError unless operator.nil? | ||||
| 
 | ||||
|         @operator = :order | ||||
|         @term = :created_at | ||||
| 
 | ||||
|  | @ -133,7 +148,7 @@ class SearchQueryTransformer < Parslet::Transform | |||
|     operator = clause[:operator]&.to_s | ||||
| 
 | ||||
|     if clause[:prefix] | ||||
|       PrefixClause.new(prefix, clause[:term].to_s) | ||||
|       PrefixClause.new(prefix, operator, clause[:term].to_s) | ||||
|     elsif clause[:term] | ||||
|       TermClause.new(prefix, operator, clause[:term].to_s) | ||||
|     elsif clause[:shortcode] | ||||
|  |  | |||
|  | @ -173,6 +173,26 @@ class Status < ApplicationRecord | |||
|     ].compact.join("\n\n") | ||||
|   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 | ||||
|     account.acct | ||||
|   end | ||||
|  |  | |||
|  | @ -34,6 +34,14 @@ class FetchLinkCardService < BaseService | |||
|     nil | ||||
|   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 | ||||
| 
 | ||||
|   def process_url | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue