Add in:library syntax to search (#26760)
				
					
				
			Co-authored-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
		
							parent
							
								
									ac3f310f4b
								
							
						
					
					
						commit
						ece1ff77d6
					
				| @ -9,23 +9,90 @@ class SearchQueryTransformer < Parslet::Transform | |||||||
|     before |     before | ||||||
|     after |     after | ||||||
|     during |     during | ||||||
|  |     in | ||||||
|   ).freeze |   ).freeze | ||||||
| 
 | 
 | ||||||
|   class Query |   class Query | ||||||
|     attr_reader :must_not_clauses, :must_clauses, :filter_clauses |     def initialize(clauses, options = {}) | ||||||
|  |       raise ArgumentError if options[:current_account].nil? | ||||||
| 
 | 
 | ||||||
|     def initialize(clauses) |       @clauses = clauses | ||||||
|       grouped = clauses.compact.chunk(&:operator).to_h |       @options = options | ||||||
|       @must_not_clauses = grouped.fetch(:must_not, []) | 
 | ||||||
|       @must_clauses = grouped.fetch(:must, []) |       flags_from_clauses! | ||||||
|       @filter_clauses = grouped.fetch(:filter, []) |  | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def apply(search) |     def request | ||||||
|  |       search = Chewy::Search::Request.new(*indexes).filter(default_filter) | ||||||
|  | 
 | ||||||
|       must_clauses.each { |clause| search = search.query.must(clause.to_query) } |       must_clauses.each { |clause| search = search.query.must(clause.to_query) } | ||||||
|       must_not_clauses.each { |clause| search = search.query.must_not(clause.to_query) } |       must_not_clauses.each { |clause| search = search.query.must_not(clause.to_query) } | ||||||
|       filter_clauses.each { |clause| search = search.filter(**clause.to_query) } |       filter_clauses.each { |clause| search = search.filter(**clause.to_query) } | ||||||
|       search.query.minimum_should_match(1) | 
 | ||||||
|  |       search | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     private | ||||||
|  | 
 | ||||||
|  |     def clauses_by_operator | ||||||
|  |       @clauses_by_operator ||= @clauses.compact.chunk(&:operator).to_h | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def flags_from_clauses! | ||||||
|  |       @flags = clauses_by_operator.fetch(:flag, []).to_h { |clause| [clause.prefix, clause.term] } | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def must_clauses | ||||||
|  |       clauses_by_operator.fetch(:must, []) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def must_not_clauses | ||||||
|  |       clauses_by_operator.fetch(:must_not, []) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def filter_clauses | ||||||
|  |       clauses_by_operator.fetch(:filter, []) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def indexes | ||||||
|  |       case @flags['in'] | ||||||
|  |       when 'library' | ||||||
|  |         [StatusesIndex] | ||||||
|  |       else | ||||||
|  |         [PublicStatusesIndex, StatusesIndex] | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def default_filter | ||||||
|  |       { | ||||||
|  |         bool: { | ||||||
|  |           should: [ | ||||||
|  |             { | ||||||
|  |               term: { | ||||||
|  |                 _index: PublicStatusesIndex.index_name, | ||||||
|  |               }, | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |               bool: { | ||||||
|  |                 must: [ | ||||||
|  |                   { | ||||||
|  |                     term: { | ||||||
|  |                       _index: StatusesIndex.index_name, | ||||||
|  |                     }, | ||||||
|  |                   }, | ||||||
|  |                   { | ||||||
|  |                     term: { | ||||||
|  |                       searchable_by: @options[:current_account].id, | ||||||
|  |                     }, | ||||||
|  |                   }, | ||||||
|  |                 ], | ||||||
|  |               }, | ||||||
|  |             }, | ||||||
|  |           ], | ||||||
|  | 
 | ||||||
|  |           minimum_should_match: 1, | ||||||
|  |         }, | ||||||
|  |       } | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| @ -108,6 +175,9 @@ class SearchQueryTransformer < Parslet::Transform | |||||||
|         @filter = :created_at |         @filter = :created_at | ||||||
|         @type = :range |         @type = :range | ||||||
|         @term = { gte: term, lte: term, time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } |         @term = { gte: term, lte: term, time_zone: @options[:current_account]&.user_time_zone.presence || 'UTC' } | ||||||
|  |       when 'in' | ||||||
|  |         @operator = :flag | ||||||
|  |         @term = term | ||||||
|       else |       else | ||||||
|         raise "Unknown prefix: #{prefix}" |         raise "Unknown prefix: #{prefix}" | ||||||
|       end |       end | ||||||
| @ -176,6 +246,6 @@ class SearchQueryTransformer < Parslet::Transform | |||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   rule(query: sequence(:clauses)) do |   rule(query: sequence(:clauses)) do | ||||||
|     Query.new(clauses) |     Query.new(clauses, current_account: current_account) | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  | |||||||
| @ -14,20 +14,8 @@ class StatusesSearchService < BaseService | |||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def status_search_results |   def status_search_results | ||||||
|     definition = parsed_query.apply( |     request             = parsed_query.request | ||||||
|       Chewy::Search::Request.new(StatusesIndex, PublicStatusesIndex).filter( |     results             = request.collapse(field: :id).order(id: { order: :desc }).limit(@limit).offset(@offset).objects.compact | ||||||
|         bool: { |  | ||||||
|           should: [ |  | ||||||
|             publicly_searchable, |  | ||||||
|             non_publicly_searchable, |  | ||||||
|           ], |  | ||||||
| 
 |  | ||||||
|           minimum_should_match: 1, |  | ||||||
|         } |  | ||||||
|       ) |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     results             = definition.collapse(field: :id).order(id: { order: :desc }).limit(@limit).offset(@offset).objects.compact |  | ||||||
|     account_ids         = results.map(&:account_id) |     account_ids         = results.map(&:account_id) | ||||||
|     account_domains     = results.map(&:account_domain) |     account_domains     = results.map(&:account_domain) | ||||||
|     preloaded_relations = @account.relations_map(account_ids, account_domains) |     preloaded_relations = @account.relations_map(account_ids, account_domains) | ||||||
| @ -37,27 +25,6 @@ class StatusesSearchService < BaseService | |||||||
|     [] |     [] | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def publicly_searchable |  | ||||||
|     { |  | ||||||
|       term: { _index: PublicStatusesIndex.index_name }, |  | ||||||
|     } |  | ||||||
|   end |  | ||||||
| 
 |  | ||||||
|   def non_publicly_searchable |  | ||||||
|     { |  | ||||||
|       bool: { |  | ||||||
|         must: [ |  | ||||||
|           { |  | ||||||
|             term: { _index: StatusesIndex.index_name }, |  | ||||||
|           }, |  | ||||||
|           { |  | ||||||
|             term: { searchable_by: @account.id }, |  | ||||||
|           }, |  | ||||||
|         ], |  | ||||||
|       }, |  | ||||||
|     } |  | ||||||
|   end |  | ||||||
| 
 |  | ||||||
|   def parsed_query |   def parsed_query | ||||||
|     SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query), current_account: @account) |     SearchQueryTransformer.new.apply(SearchQueryParser.new.parse(@query), current_account: @account) | ||||||
|   end |   end | ||||||
|  | |||||||
| @ -3,17 +3,18 @@ | |||||||
| require 'rails_helper' | require 'rails_helper' | ||||||
| 
 | 
 | ||||||
| describe SearchQueryTransformer do | describe SearchQueryTransformer do | ||||||
|   subject { described_class.new.apply(parser, current_account: nil) } |   subject { described_class.new.apply(parser, current_account: account) } | ||||||
| 
 | 
 | ||||||
|  |   let(:account) { Fabricate(:account) } | ||||||
|   let(:parser) { SearchQueryParser.new.parse(query) } |   let(:parser) { SearchQueryParser.new.parse(query) } | ||||||
| 
 | 
 | ||||||
|   context 'with "hello world"' do |   context 'with "hello world"' do | ||||||
|     let(:query) { 'hello world' } |     let(:query) { 'hello world' } | ||||||
| 
 | 
 | ||||||
|     it 'transforms clauses' do |     it 'transforms clauses' do | ||||||
|       expect(subject.must_clauses.map(&:term)).to match_array %w(hello world) |       expect(subject.send(:must_clauses).map(&:term)).to match_array %w(hello world) | ||||||
|       expect(subject.must_not_clauses).to be_empty |       expect(subject.send(:must_not_clauses)).to be_empty | ||||||
|       expect(subject.filter_clauses).to be_empty |       expect(subject.send(:filter_clauses)).to be_empty | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| @ -21,9 +22,9 @@ describe SearchQueryTransformer do | |||||||
|     let(:query) { 'hello -world' } |     let(:query) { 'hello -world' } | ||||||
| 
 | 
 | ||||||
|     it 'transforms clauses' do |     it 'transforms clauses' do | ||||||
|       expect(subject.must_clauses.map(&:term)).to match_array %w(hello) |       expect(subject.send(:must_clauses).map(&:term)).to match_array %w(hello) | ||||||
|       expect(subject.must_not_clauses.map(&:term)).to match_array %w(world) |       expect(subject.send(:must_not_clauses).map(&:term)).to match_array %w(world) | ||||||
|       expect(subject.filter_clauses).to be_empty |       expect(subject.send(:filter_clauses)).to be_empty | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| @ -31,9 +32,9 @@ describe SearchQueryTransformer do | |||||||
|     let(:query) { 'hello is:reply' } |     let(:query) { 'hello is:reply' } | ||||||
| 
 | 
 | ||||||
|     it 'transforms clauses' do |     it 'transforms clauses' do | ||||||
|       expect(subject.must_clauses.map(&:term)).to match_array %w(hello) |       expect(subject.send(:must_clauses).map(&:term)).to match_array %w(hello) | ||||||
|       expect(subject.must_not_clauses).to be_empty |       expect(subject.send(:must_not_clauses)).to be_empty | ||||||
|       expect(subject.filter_clauses.map(&:term)).to match_array %w(reply) |       expect(subject.send(:filter_clauses).map(&:term)).to match_array %w(reply) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| @ -41,9 +42,9 @@ describe SearchQueryTransformer do | |||||||
|     let(:query) { 'foo: bar' } |     let(:query) { 'foo: bar' } | ||||||
| 
 | 
 | ||||||
|     it 'transforms clauses' do |     it 'transforms clauses' do | ||||||
|       expect(subject.must_clauses.map(&:term)).to match_array %w(foo bar) |       expect(subject.send(:must_clauses).map(&:term)).to match_array %w(foo bar) | ||||||
|       expect(subject.must_not_clauses).to be_empty |       expect(subject.send(:must_not_clauses)).to be_empty | ||||||
|       expect(subject.filter_clauses).to be_empty |       expect(subject.send(:filter_clauses)).to be_empty | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| @ -51,9 +52,9 @@ describe SearchQueryTransformer do | |||||||
|     let(:query) { 'foo:bar' } |     let(:query) { 'foo:bar' } | ||||||
| 
 | 
 | ||||||
|     it 'transforms clauses' do |     it 'transforms clauses' do | ||||||
|       expect(subject.must_clauses.map(&:term)).to contain_exactly('foo bar') |       expect(subject.send(:must_clauses).map(&:term)).to contain_exactly('foo bar') | ||||||
|       expect(subject.must_not_clauses).to be_empty |       expect(subject.send(:must_not_clauses)).to be_empty | ||||||
|       expect(subject.filter_clauses).to be_empty |       expect(subject.send(:filter_clauses)).to be_empty | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user