diff --git a/.yardopts b/.yardopts index 98b43161c..b2f00bf20 100644 --- a/.yardopts +++ b/.yardopts @@ -1,2 +1,5 @@ --markup-provider=redcarpet --markup=markdown +- +README.md +CHANGELOG.md diff --git a/lib/chewy/search/parameters/concerns/query_storage.rb b/lib/chewy/search/parameters/concerns/query_storage.rb index c4ac052a9..271400501 100644 --- a/lib/chewy/search/parameters/concerns/query_storage.rb +++ b/lib/chewy/search/parameters/concerns/query_storage.rb @@ -3,12 +3,12 @@ module Chewy module Search class Parameters - # This is a basic storage implementation for "query", "filter" - # and "post_filter" storages. It uses "bool" query as a root - # structure for each of them. The "bool" root is ommited on - # rendering if there is only a single query in the "must" or - # "should" array. Besides the standard parameter storage - # capabilities, it provides specialized methods for the "bool" + # This is a basic storage implementation for `query`, `filter` + # and `post_filter` storages. It uses `bool` query as a root + # structure for each of them. The `bool` root is ommited on + # rendering if there is only a single query in the `must` or + # `should` array. Besides the standard parameter storage + # capabilities, it provides specialized methods for the `bool` # query component arrays separate update. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html @@ -18,7 +18,7 @@ class Parameters module QueryStorage DEFAULT = {must: [], should: [], must_not: []}.freeze - # Directly modifies "must" array of the root "bool" query. + # Directly modifies `must` array of the root `bool` query. # Pushes the passed query to the end of the array. # # @see Chewy::Search::QueryProxy#must @@ -26,7 +26,7 @@ def must(other_value) update!(must: other_value) end - # Directly modifies "should" array of the root "bool" query. + # Directly modifies `should` array of the root `bool` query. # Pushes the passed query to the end of the array. # # @see Chewy::Search::QueryProxy#should @@ -34,7 +34,7 @@ def should(other_value) update!(should: other_value) end - # Directly modifies "must_not" array of the root "bool" query. + # Directly modifies `must_not` array of the root `bool` query. # Pushes the passed query to the end of the array. # # @see Chewy::Search::QueryProxy#must_not @@ -42,10 +42,10 @@ def must_not(other_value) update!(must_not: other_value) end - # Unlike {#must} doesn't modify "must" array, but joins 2 queries - # into a single "must" array of the new root "bool" query. - # If any of the used queries is a "bool" query from the storage - # and contains a single query in "must" or "should" array, it will + # Unlike {#must} doesn't modify `must` array, but joins 2 queries + # into a single `must` array of the new root `bool` query. + # If any of the used queries is a `bool` query from the storage + # and contains a single query in `must` or `should` array, it will # be reduced to this query, so in some cases it will act exactly # the same way as {#must}. # @@ -54,10 +54,10 @@ def and(other_value) replace!(must: join(other_value)) end - # Unlike {#should} doesn't modify "should" array, but joins 2 queries - # into a single "should" array of the new root "bool" query. - # If any of the used queries is a "bool" query from the storage - # and contains a single query in "must" or "should" array, it will + # Unlike {#should} doesn't modify `should` array, but joins 2 queries + # into a single `should` array of the new root `bool` query. + # If any of the used queries is a `bool` query from the storage + # and contains a single query in `must` or `should` array, it will # be reduced to this query, so in some cases it will act exactly # the same way as {#should}. # diff --git a/lib/chewy/search/parameters/filter.rb b/lib/chewy/search/parameters/filter.rb index 73393cade..be24af590 100644 --- a/lib/chewy/search/parameters/filter.rb +++ b/lib/chewy/search/parameters/filter.rb @@ -4,14 +4,16 @@ module Chewy module Search class Parameters # This parameter storage doesn't have its own parameter at the - # ES request body. Instead, it is embedded to the root "bool" - # query of the "query" request parameter. + # ES request body. Instead, it is embedded to the root `bool` + # query of the `query` request parameter. # # @example # scope = PlacesIndex.filter(term: {name: 'Moscow'}) # # => {:query=>{:bool=>{:filter=>{:term=>{:name=>"Moscow"}}}}}}> # scope.query(match: {name: 'London'}) - # # => {:query=>{:bool=>{:must=>{:match=>{:name=>"London"}}, :filter=>{:term=>{:name=>"Moscow"}}}}}}> + # # => {:query=>{:bool=>{ + # # :must=>{:match=>{:name=>"London"}}, + # # :filter=>{:term=>{:name=>"Moscow"}}}}}}> # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html # @see Chewy::Search::Parameters::QueryStorage class Filter < Storage diff --git a/lib/chewy/search/parameters/post_filter.rb b/lib/chewy/search/parameters/post_filter.rb index e24e6b23f..7ea566df4 100644 --- a/lib/chewy/search/parameters/post_filter.rb +++ b/lib/chewy/search/parameters/post_filter.rb @@ -3,7 +3,7 @@ module Chewy module Search class Parameters - # A standard parameter storage, which updates "post_filter" parameter + # A standard parameter storage, which updates `post_filter` parameter # of the ES request. # # @example diff --git a/lib/chewy/search/parameters/query.rb b/lib/chewy/search/parameters/query.rb index 74f866f47..38548f500 100644 --- a/lib/chewy/search/parameters/query.rb +++ b/lib/chewy/search/parameters/query.rb @@ -3,7 +3,7 @@ module Chewy module Search class Parameters - # A standard parameter storage, which updates "query" parameter + # A standard parameter storage, which updates `query` parameter # of the ES request. # # @example diff --git a/lib/chewy/search/query_proxy.rb b/lib/chewy/search/query_proxy.rb index 092360846..8429d73fa 100644 --- a/lib/chewy/search/query_proxy.rb +++ b/lib/chewy/search/query_proxy.rb @@ -1,7 +1,7 @@ module Chewy module Search # This specialized proxy class is used to provide an ability - # of "query", "filter", "post_filter" parameters additional + # of `query`, `filter`, `post_filter` parameters additional # modification. # # @see Chewy::Search::Parameters::Query @@ -23,23 +23,25 @@ def initialize(parameter_name, request) # @return [Chewy::Search::Request] # # @overload must(query_hash) - # If pure hash is passed it is added to "must" array of the bool query. + # If pure hash is passed it is added to `must` array of the bool query. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html # @example # PlacesIndex.query.must(match: {name: 'Moscow'}).query.must(match: {name: 'London'}) - # # => {:query=>{:bool=>{:must=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :must=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> # @param query_hash [Hash] pure query hash # # @overload must - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # # @see https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl # @example # PlacesIndex.query.must { match name: 'Moscow' }.query.must { match name: 'London' } - # # => {:query=>{:bool=>{:must=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # # => {:query=>{:bool=>{ + # # :must=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # @yield the block is processed by `elasticsearch-dsl` gem # # @!method should(query_hash = nil, &block) # (see Chewy::Search::Parameters::QueryStorage#should) @@ -48,23 +50,25 @@ def initialize(parameter_name, request) # @return [Chewy::Search::Request] # # @overload should(query_hash) - # If pure hash is passed it is added to "should" array of the bool query. + # If pure hash is passed it is added to `should` array of the bool query. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html # @example # PlacesIndex.query.should(match: {name: 'Moscow'}).query.should(match: {name: 'London'}) - # # => {:query=>{:bool=>{:should=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :should=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> # @param query_hash [Hash] pure query hash # # @overload should - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # # @see https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl # @example # PlacesIndex.query.should { match name: 'Moscow' }.query.should { match name: 'London' } - # # => {:query=>{:bool=>{:should=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # # => {:query=>{:bool=>{ + # # :should=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # @yield the block is processed by `elasticsearch-dsl` gem # # @!method must_not(query_hash = nil, &block) # (see Chewy::Search::Parameters::QueryStorage#must_not) @@ -73,23 +77,25 @@ def initialize(parameter_name, request) # @return [Chewy::Search::Request] # # @overload must_not(query_hash) - # If pure hash is passed it is added to "must_not" array of the bool query. + # If pure hash is passed it is added to `must_not` array of the bool query. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html # @example # PlacesIndex.query.must_not(match: {name: 'Moscow'}).query.must_not(match: {name: 'London'}) - # # => {:query=>{:bool=>{:must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> # @param query_hash [Hash] pure query hash # # @overload must_not - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # # @see https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl # @example # PlacesIndex.query.must_not { match name: 'Moscow' }.query.must_not { match name: 'London' } - # # => {:query=>{:bool=>{:must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # # => {:query=>{:bool=>{ + # # :must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # @yield the block is processed by `elasticsearch-dsl` gem %i[must should must_not].each do |method| define_method method do |query_hash = nil, &block| raise ArgumentError, "Please provide a parameter or a block to `#{method}`" unless query_hash || block @@ -104,17 +110,19 @@ def initialize(parameter_name, request) # @return [Chewy::Search::Request] # # @overload and(query_hash) - # If pure hash is passed, the current root "bool" query and - # the passed one are joined into a single "must" array of the + # If pure hash is passed, the current root `bool` query and + # the passed one are joined into a single `must` array of the # new root query. # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html # @example # scope = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope.query.and(match: {name: 'London'}) - # # => {:query=>{:bool=>{:must=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :must=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> # scope = PlacesIndex.query(match: {name: 'Moscow'}) # scope.query.and(match: {name: 'London'}) - # # => {:query=>{:bool=>{:must=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :must=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> # @param query_hash [Hash] pure query hash # # @overload and(scope) @@ -124,18 +132,20 @@ def initialize(parameter_name, request) # scope1 = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope2 = PlacesIndex.query(match: {name: 'London'}) # scope1.query.and(scope2) - # # => {:query=>{:bool=>{:must=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :must=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> # @param scope [Chewy::Search::Request] other scope # # @overload and - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # @see https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl # @example # scope = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope.query.and { match name: 'London' } - # # => {:query=>{:bool=>{:must=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # # => {:query=>{:bool=>{ + # # :must=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> + # @yield the block is processed by `elasticsearch-dsl` gem # # @!method or(query_hash_or_scope = nil, &block) # (see Chewy::Search::Parameters::QueryStorage#or) @@ -144,17 +154,19 @@ def initialize(parameter_name, request) # @return [Chewy::Search::Request] # # @overload or(query_hash) - # If pure hash is passed, the current root "bool" query and - # the passed one are joined into a single "should" array of the + # If pure hash is passed, the current root `bool` query and + # the passed one are joined into a single `should` array of the # new root query. # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html # @example # scope = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope.query.or(match: {name: 'London'}) - # # => {:query=>{:bool=>{:should=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :should=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> # scope = PlacesIndex.query(match: {name: 'Moscow'}) # scope.query.or(match: {name: 'London'}) - # # => {:query=>{:bool=>{:should=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :should=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> # @param query_hash [Hash] pure query hash # # @overload or(scope) @@ -164,18 +176,20 @@ def initialize(parameter_name, request) # scope1 = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope2 = PlacesIndex.query(match: {name: 'London'}) # scope1.query.or(scope2) - # # => {:query=>{:bool=>{:should=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :should=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> # @param scope [Chewy::Search::Request] other scope # # @overload or - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # @see https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl # @example # scope = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope.query.or { match name: 'London' } - # # => {:query=>{:bool=>{:should=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # # => {:query=>{:bool=>{ + # # :should=>[{:bool=>{:must_not=>{:match=>{:name=>"Moscow"}}}}, {:match=>{:name=>"London"}}]}}}}> + # @yield the block is processed by `elasticsearch-dsl` gem # # @!method not(query_hash_or_scope = nil, &block) # (see Chewy::Search::Parameters::QueryStorage#not) @@ -185,12 +199,13 @@ def initialize(parameter_name, request) # @return [Chewy::Search::Request] # # @overload not(query_hash) - # If pure hash is passed it is added to "must_not" array of the bool query. + # If pure hash is passed it is added to `must_not` array of the bool query. # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html # @example # scope = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope.query.not(match: {name: 'London'}) - # # => {:query=>{:bool=>{:must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> # @param query_hash [Hash] pure query hash # # @overload not(scope) @@ -200,18 +215,20 @@ def initialize(parameter_name, request) # scope1 = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope2 = PlacesIndex.query(match: {name: 'London'}) # scope1.query.not(scope2) - # # => {:query=>{:bool=>{:must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # # => {:query=>{:bool=>{ + # # :must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> # @param scope [Chewy::Search::Request] other scope # # @overload not - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # @see https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl # @example # scope = PlacesIndex.query.must_not(match: {name: 'Moscow'}) # scope.query.not { match name: 'London' } - # # => {:query=>{:bool=>{:must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # # => {:query=>{:bool=>{ + # # :must_not=>[{:match=>{:name=>"Moscow"}}, {:match=>{:name=>"London"}}]}}}}> + # @yield the block is processed by `elasticsearch-dsl` gem %i[and or not].each do |method| define_method method do |query_hash_or_scope = nil, &block| raise ArgumentError, "Please provide a parameter or a block to `#{method}`" unless query_hash_or_scope || block diff --git a/lib/chewy/search/request.rb b/lib/chewy/search/request.rb index adef556c0..fad92f377 100644 --- a/lib/chewy/search/request.rb +++ b/lib/chewy/search/request.rb @@ -108,14 +108,14 @@ def inspect # @!group Chainable request modificators # @!method query(query_hash=nil, &block) - # Adds "query" parameter to the search request body. + # Adds `quer` parameter to the search request body. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-query.html # @see Chewy::Search::Parameters::Query # @return [Chewy::Search::Request, Chewy::Search::QueryProxy] # # @overload query(query_hash) - # If pure hash is passed it goes straight to the "query" parameter storage. + # If pure hash is passed it goes straight to the `quer` parameter storage. # Acts exactly the same way as {Chewy::Search::QueryProxy#must}. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html @@ -126,7 +126,7 @@ def inspect # @return [Chewy::Search::Request] # # @overload query - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # Acts exactly the same way as {Chewy::Search::QueryProxy#must} with a block. # @@ -134,7 +134,7 @@ def inspect # @example # PlacesIndex.query { match name: 'Moscow' } # # => {:query=>{:match=>{:name=>"Moscow"}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # @yield the block is processed by `elasticsearch-ds` gem # @return [Chewy::Search::Request] # # @overload query @@ -144,11 +144,13 @@ def inspect # @see Chewy::Search::QueryProxy # @example # PlacesIndex.query.should(match: {name: 'Moscow'}).query.not(match: {name: 'London'}) - # # => {:query=>{:bool=>{:should=>{:match=>{:name=>"Moscow"}}, :must_not=>{:match=>{:name=>"London"}}}}}}> + # # => {:query=>{:bool=>{ + # # :should=>{:match=>{:name=>"Moscow"}}, + # # :must_not=>{:match=>{:name=>"London"}}}}}}> # @return [Chewy::Search::QueryProxy] # # @!method filter(query_hash=nil, &block) - # Adds "filter" context of the "query" parameter at the + # Adds `filte` context of the `quer` parameter at the # search request body. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html @@ -156,26 +158,28 @@ def inspect # @return [Chewy::Search::Request, Chewy::Search::QueryProxy] # # @overload filter(query_hash) - # If pure hash is passed it goes straight to the "filter" context of the "query" parameter storage. + # If pure hash is passed it goes straight to the `filte` context of the `quer` parameter storage. # Acts exactly the same way as {Chewy::Search::QueryProxy#must}. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html # @example # PlacesIndex.filter(match: {name: 'Moscow'}) - # # => {:query=>{:bool=>{:filter=>{:match=>{:name=>"Moscow"}}}}}}> + # # => {:query=>{:bool=>{ + # # :filter=>{:match=>{:name=>"Moscow"}}}}}}> # @param query_hash [Hash] pure query hash # @return [Chewy::Search::Request] # # @overload filter - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # Acts exactly the same way as {Chewy::Search::QueryProxy#must} with a block. # # @see https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl # @example # PlacesIndex.filter { match name: 'Moscow' } - # # => {:query=>{:bool=>{:filter=>{:match=>{:name=>"Moscow"}}}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # # => {:query=>{:bool=>{ + # # :filter=>{:match=>{:name=>"Moscow"}}}}}}> + # @yield the block is processed by `elasticsearch-ds` gem # @return [Chewy::Search::Request] # # @overload filter @@ -185,18 +189,20 @@ def inspect # @see Chewy::Search::QueryProxy # @example # PlacesIndex.filter.should(match: {name: 'Moscow'}).filter.not(match: {name: 'London'}) - # # => {:query=>{:bool=>{:filter=>{:bool=>{:should=>{:match=>{:name=>"Moscow"}}, :must_not=>{:match=>{:name=>"London"}}}}}}}}> + # # => {:query=>{:bool=>{ + # # :filter=>{:bool=>{:should=>{:match=>{:name=>"Moscow"}}, + # # :must_not=>{:match=>{:name=>"London"}}}}}}}}> # @return [Chewy::Search::QueryProxy] # # @!method post_filter(query_hash=nil, &block) - # Adds "post_filter" parameter to the search request body. + # Adds `post_filter` parameter to the search request body. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-post-filter.html # @see Chewy::Search::Parameters::PostFilter # @return [Chewy::Search::Request, Chewy::Search::QueryProxy] # # @overload post_filter(query_hash) - # If pure hash is passed it goes straight to the "post_filter" parameter storage. + # If pure hash is passed it goes straight to the `post_filter` parameter storage. # Acts exactly the same way as {Chewy::Search::QueryProxy#must}. # # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html @@ -207,7 +213,7 @@ def inspect # @return [Chewy::Search::Request] # # @overload post_filter - # If block is passed instead of a pure hash, "elasticsearch-dsl" + # If block is passed instead of a pure hash, `elasticsearch-dsl" # gem will be used to process it. # Acts exactly the same way as {Chewy::Search::QueryProxy#must} with a block. # @@ -215,7 +221,7 @@ def inspect # @example # PlacesIndex.post_filter { match name: 'Moscow' } # # => {:post_filter=>{:match=>{:name=>"Moscow"}}}}> - # @yield the block is processed by "elasticsearch-dsl" gem + # @yield the block is processed by `elasticsearch-ds` gem # @return [Chewy::Search::Request] # # @overload post_filter @@ -225,7 +231,9 @@ def inspect # @see Chewy::Search::QueryProxy # @example # PlacesIndex.post_filter.should(match: {name: 'Moscow'}).post_filter.not(match: {name: 'London'}) - # # => {:post_filter=>{:bool=>{:should=>{:match=>{:name=>"Moscow"}}, :must_not=>{:match=>{:name=>"London"}}}}}}> + # # => {:post_filter=>{:bool=>{ + # # :should=>{:match=>{:name=>"Moscow"}}, + # # :must_not=>{:match=>{:name=>"London"}}}}}}> # @return [Chewy::Search::QueryProxy] %i[query filter post_filter].each do |name| define_method name do |query_hash = nil, &block| @@ -306,7 +314,7 @@ def merge(other) end # @!method and(other) - # Takes "query", "filter", "post_filter" from the passed scope + # Takes `query`, `filter`, `post_filter` from the passed scope # and performs {Chewy::Search::QueryProxy#and} operation for each # of them. Unlike merge, every other parameter is kept unmerged # (values from the first scope are used in the result scope). @@ -323,7 +331,7 @@ def merge(other) # @return [Chewy::Search::Request] new scope # # @!method or(other) - # Takes "query", "filter", "post_filter" from the passed scope + # Takes `query`, `filter`, `post_filter` from the passed scope # and performs {Chewy::Search::QueryProxy#or} operation for each # of them. Unlike merge, every other parameter is kept unmerged # (values from the first scope are used in the result scope). @@ -340,7 +348,7 @@ def merge(other) # @return [Chewy::Search::Request] new scope # # @!method not(other) - # Takes "query", "filter", "post_filter" from the passed scope + # Takes `query`, `filter`, `post_filter` from the passed scope # and performs {Chewy::Search::QueryProxy#not} operation for each # of them. Unlike merge, every other parameter is kept unmerged # (values from the first scope are used in the result scope). @@ -387,19 +395,6 @@ def except(*values) # @!group Additional actions - def delete_all - ActiveSupport::Notifications.instrument 'delete_query.chewy', - request: render_simple, indexes: _indexes, types: _types, - index: _indexes.one? ? _indexes.first : _indexes, - type: _types.one? ? _types.first : _types do - if Runtime.version < '5.0' - delete_by_query_plugin(render_simple) - else - Chewy.client.delete_by_query(render_simple) - end - end - end - def count if instance_variable_defined?(:@response) response.total @@ -441,6 +436,19 @@ def pluck(*fields) end end + def delete_all + ActiveSupport::Notifications.instrument 'delete_query.chewy', + request: render_simple, indexes: _indexes, types: _types, + index: _indexes.one? ? _indexes.first : _indexes, + type: _types.one? ? _types.first : _types do + if Runtime.version < '5.0' + delete_by_query_plugin(render_simple) + else + Chewy.client.delete_by_query(render_simple) + end + end + end + protected def initialize_clone(origin) diff --git a/spec/chewy/search/request_spec.rb b/spec/chewy/search/request_spec.rb index 274c8f287..41b1f91db 100644 --- a/spec/chewy/search/request_spec.rb +++ b/spec/chewy/search/request_spec.rb @@ -19,187 +19,6 @@ subject { described_class.new(ProductsIndex) } - context 'index does not exist' do - specify { expect(subject).to eq([]) } - end - - context 'integration' do - let(:products) { Array.new(3) { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } } - let(:cities) { Array.new(3) { |i| {id: (i.next + 3).to_s}.stringify_keys! } } - let(:countries) { Array.new(3) { |i| {id: (i.next + 6).to_s}.stringify_keys! } } - before do - ProductsIndex::Product.import!(products.map { |h| double(h) }) - ProductsIndex::City.import!(cities.map { |h| double(h) }) - ProductsIndex::Country.import!(countries.map { |h| double(h) }) - CitiesIndex::City.import!(cities.map { |h| double(h) }) - end - - specify { expect(subject.first._data).to be_a Hash } - - context 'another index' do - subject { described_class.new(CitiesIndex) } - - specify { expect(subject.count).to eq(3) } - specify { expect(subject.size).to eq(3) } - end - - context 'limited types' do - subject { described_class.new(ProductsIndex::City, ProductsIndex::Country) } - - specify { expect(subject.count).to eq(6) } - specify { expect(subject.size).to eq(6) } - end - - context 'mixed types' do - subject { described_class.new(CitiesIndex, ProductsIndex::Product) } - - specify { expect(subject.count).to eq(9) } - specify { expect(subject.size).to eq(9) } - end - - describe '#total' do - specify { expect(subject.limit(6).total).to eq(9) } - specify { expect(subject.limit(6).total_count).to eq(9) } - specify { expect(subject.offset(6).total_entries).to eq(9) } - end - - describe '#highlight' do - specify { expect(subject.query(match: {name: 'name3'}).highlight(fields: {name: {}}).first.name).to eq('Name3') } - specify { expect(subject.query(match: {name: 'name3'}).highlight(fields: {name: {}}).first.name_highlight).to eq('Name3') } - specify { expect(subject.query(match: {name: 'name3'}).highlight(fields: {name: {}}).first._data['_source']['name']).to eq('Name3') } - end - - describe '#delete_all' do - specify do - expect do - subject.query(match: {name: 'name3'}).delete_all - Chewy.client.indices.refresh(index: 'products') - end.to change { described_class.new(ProductsIndex).total }.from(9).to(8) - end - specify do - expect do - subject.filter(range: {age: {gte: 10, lte: 20}}).delete_all - Chewy.client.indices.refresh(index: 'products') - end.to change { described_class.new(ProductsIndex).total_count }.from(9).to(7) - end - specify do - expect do - subject.types(:product).delete_all - Chewy.client.indices.refresh(index: 'products') - end.to change { described_class.new(ProductsIndex::Product).total_entries }.from(3).to(0) - end - specify do - expect do - subject.delete_all - Chewy.client.indices.refresh(index: 'products') - end.to change { described_class.new(ProductsIndex).total }.from(9).to(0) - end - specify do - expect do - described_class.new(ProductsIndex::City).delete_all - Chewy.client.indices.refresh(index: 'products') - end.to change { described_class.new(ProductsIndex).total }.from(9).to(6) - end - - specify do - outer_payload = nil - ActiveSupport::Notifications.subscribe('delete_query.chewy') do |_name, _start, _finish, _id, payload| - outer_payload = payload - end - subject.query(match: {name: 'name3'}).delete_all - expect(outer_payload).to eq( - index: ProductsIndex, - indexes: [ProductsIndex], - request: {index: ['products'], type: %w[product city country], body: {query: {match: {name: 'name3'}}}}, - type: [ProductsIndex::Product, ProductsIndex::City, ProductsIndex::Country], - types: [ProductsIndex::Product, ProductsIndex::City, ProductsIndex::Country] - ) - end - - describe '#exists?' do - specify { expect(subject.exists?).to be(true) } - specify { expect(subject.filter(match: {name: 'foo'}).exist?).to be(false) } - end - - describe '#find' do - specify { expect(subject.find('1')).to be_a(ProductsIndex::Product).and have_attributes(id: '1') } - specify { expect(subject.limit(2).find('1', '3', '7').map(&:id)).to contain_exactly('1', '3', '7') } - specify { expect { subject.find('1', '3', '42') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 42' } - specify { expect { subject.query(match: {name: 'name3'}).find('1', '3') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 1' } - specify { expect { subject.query(match: {name: 'name2'}).find('1', '3') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 1 and 3' } - specify { expect { subject.filter(match: {name: 'name2'}).find('1', '3') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 1 and 3' } - specify { expect { subject.post_filter(match: {name: 'name2'}).find('1', '3') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 1 and 3' } - end - - describe '#pluck' do - specify { expect(subject.limit(5).pluck(:id)).to eq(%w[1 2 3 4 5]) } - specify { expect(subject.limit(5).pluck(:id, :age)).to eq([['1', 10], ['2', 20], ['3', 30], ['4', nil], ['5', nil]]) } - specify { expect(subject.limit(5).source(:name).pluck(:id, :age)).to eq([['1', 10], ['2', 20], ['3', 30], ['4', nil], ['5', nil]]) } - specify do - expect(subject.limit(5).pluck(:index, :type, :name)).to eq([ - %w[products product Name1], - %w[products product Name2], - %w[products product Name3], - ['products', 'city', nil], - ['products', 'city', nil] - ]) - end - end - end - - describe '#size' do - specify { expect(subject.size).to eq(9) } - specify { expect(subject.limit(6).size).to eq(6) } - specify { expect(subject.offset(6).size).to eq(3) } - end - - describe '#count' do - specify { expect(subject.count).to eq(9) } - specify { expect(subject.limit(6).count).to eq(9) } - specify { expect(subject.offset(6).count).to eq(9) } - specify { expect(subject.types(:product, :something).count).to eq(3) } - specify { expect(subject.types(:product, :country).count).to eq(6) } - specify { expect(subject.filter(term: {age: 10}).count).to eq(1) } - specify { expect(subject.query(term: {age: 10}).count).to eq(1) } - specify { expect(subject.order(nil).count).to eq(9) } - - context do - before { expect(Chewy.client).to receive(:count).and_call_original } - specify { subject.count } - end - - context do - before { expect(Chewy.client).not_to receive(:count) } - before { subject.total } - specify { expect(subject.limit(6).count).to eq(9) } - end - end - - describe '#none' do - specify { expect(subject.none.render).not_to have_key(:body) } - specify { expect(subject.none).to eq([]) } - end - - describe '#suggest' do - specify do - expect(subject.suggest( - foo: { - text: 'name', - term: {field: 'name'} - } - ).suggest).to eq( - 'foo' => [ - {'text' => 'name', 'offset' => 0, 'length' => 4, 'options' => [ - {'text' => 'name1', 'score' => 0.75, 'freq' => 1}, - {'text' => 'name2', 'score' => 0.75, 'freq' => 1}, - {'text' => 'name3', 'score' => 0.75, 'freq' => 1} - ]} - ] - ) - end - end - end - describe '#==' do specify { expect(described_class.new(ProductsIndex)).to eq(described_class.new(ProductsIndex)) } specify { expect(described_class.new(ProductsIndex)).not_to eq(described_class.new(CitiesIndex)) } @@ -527,4 +346,185 @@ specify { expect(subject.except(:limit)).to eq(described_class.new(ProductsIndex).offset(10)) } specify { expect { subject.except(:limit) }.not_to change { subject.render } } end + + context 'index does not exist' do + specify { expect(subject).to eq([]) } + end + + context 'integration' do + let(:products) { Array.new(3) { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } } + let(:cities) { Array.new(3) { |i| {id: (i.next + 3).to_s}.stringify_keys! } } + let(:countries) { Array.new(3) { |i| {id: (i.next + 6).to_s}.stringify_keys! } } + before do + ProductsIndex::Product.import!(products.map { |h| double(h) }) + ProductsIndex::City.import!(cities.map { |h| double(h) }) + ProductsIndex::Country.import!(countries.map { |h| double(h) }) + CitiesIndex::City.import!(cities.map { |h| double(h) }) + end + + specify { expect(subject.first._data).to be_a Hash } + + context 'another index' do + subject { described_class.new(CitiesIndex) } + + specify { expect(subject.count).to eq(3) } + specify { expect(subject.size).to eq(3) } + end + + context 'limited types' do + subject { described_class.new(ProductsIndex::City, ProductsIndex::Country) } + + specify { expect(subject.count).to eq(6) } + specify { expect(subject.size).to eq(6) } + end + + context 'mixed types' do + subject { described_class.new(CitiesIndex, ProductsIndex::Product) } + + specify { expect(subject.count).to eq(9) } + specify { expect(subject.size).to eq(9) } + end + + describe '#none' do + specify { expect(subject.none.render).not_to have_key(:body) } + specify { expect(subject.none).to eq([]) } + end + + describe '#highlight' do + specify { expect(subject.query(match: {name: 'name3'}).highlight(fields: {name: {}}).first.name).to eq('Name3') } + specify { expect(subject.query(match: {name: 'name3'}).highlight(fields: {name: {}}).first.name_highlight).to eq('Name3') } + specify { expect(subject.query(match: {name: 'name3'}).highlight(fields: {name: {}}).first._data['_source']['name']).to eq('Name3') } + end + + describe '#suggest' do + specify do + expect(subject.suggest( + foo: { + text: 'name', + term: {field: 'name'} + } + ).suggest).to eq( + 'foo' => [ + {'text' => 'name', 'offset' => 0, 'length' => 4, 'options' => [ + {'text' => 'name1', 'score' => 0.75, 'freq' => 1}, + {'text' => 'name2', 'score' => 0.75, 'freq' => 1}, + {'text' => 'name3', 'score' => 0.75, 'freq' => 1} + ]} + ] + ) + end + end + + describe '#size' do + specify { expect(subject.size).to eq(9) } + specify { expect(subject.limit(6).size).to eq(6) } + specify { expect(subject.offset(6).size).to eq(3) } + end + + describe '#total' do + specify { expect(subject.limit(6).total).to eq(9) } + specify { expect(subject.limit(6).total_count).to eq(9) } + specify { expect(subject.offset(6).total_entries).to eq(9) } + end + + describe '#count' do + specify { expect(subject.count).to eq(9) } + specify { expect(subject.limit(6).count).to eq(9) } + specify { expect(subject.offset(6).count).to eq(9) } + specify { expect(subject.types(:product, :something).count).to eq(3) } + specify { expect(subject.types(:product, :country).count).to eq(6) } + specify { expect(subject.filter(term: {age: 10}).count).to eq(1) } + specify { expect(subject.query(term: {age: 10}).count).to eq(1) } + specify { expect(subject.order(nil).count).to eq(9) } + + context do + before { expect(Chewy.client).to receive(:count).and_call_original } + specify { subject.count } + end + + context do + before { expect(Chewy.client).not_to receive(:count) } + before { subject.total } + specify { expect(subject.limit(6).count).to eq(9) } + end + end + + describe '#exists?' do + specify { expect(subject.exists?).to be(true) } + specify { expect(subject.filter(match: {name: 'foo'}).exist?).to be(false) } + end + + describe '#find' do + specify { expect(subject.find('1')).to be_a(ProductsIndex::Product).and have_attributes(id: '1') } + specify { expect(subject.limit(2).find('1', '3', '7').map(&:id)).to contain_exactly('1', '3', '7') } + specify { expect { subject.find('1', '3', '42') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 42' } + specify { expect { subject.query(match: {name: 'name3'}).find('1', '3') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 1' } + specify { expect { subject.query(match: {name: 'name2'}).find('1', '3') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 1 and 3' } + specify { expect { subject.filter(match: {name: 'name2'}).find('1', '3') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 1 and 3' } + specify { expect { subject.post_filter(match: {name: 'name2'}).find('1', '3') }.to raise_error Chewy::DocumentNotFound, 'Could not find documents for ids: 1 and 3' } + end + + describe '#pluck' do + specify { expect(subject.limit(5).pluck(:id)).to eq(%w[1 2 3 4 5]) } + specify { expect(subject.limit(5).pluck(:id, :age)).to eq([['1', 10], ['2', 20], ['3', 30], ['4', nil], ['5', nil]]) } + specify { expect(subject.limit(5).source(:name).pluck(:id, :age)).to eq([['1', 10], ['2', 20], ['3', 30], ['4', nil], ['5', nil]]) } + specify do + expect(subject.limit(5).pluck(:index, :type, :name)).to eq([ + %w[products product Name1], + %w[products product Name2], + %w[products product Name3], + ['products', 'city', nil], + ['products', 'city', nil] + ]) + end + end + + describe '#delete_all' do + specify do + expect do + subject.query(match: {name: 'name3'}).delete_all + Chewy.client.indices.refresh(index: 'products') + end.to change { described_class.new(ProductsIndex).total }.from(9).to(8) + end + specify do + expect do + subject.filter(range: {age: {gte: 10, lte: 20}}).delete_all + Chewy.client.indices.refresh(index: 'products') + end.to change { described_class.new(ProductsIndex).total_count }.from(9).to(7) + end + specify do + expect do + subject.types(:product).delete_all + Chewy.client.indices.refresh(index: 'products') + end.to change { described_class.new(ProductsIndex::Product).total_entries }.from(3).to(0) + end + specify do + expect do + subject.delete_all + Chewy.client.indices.refresh(index: 'products') + end.to change { described_class.new(ProductsIndex).total }.from(9).to(0) + end + specify do + expect do + described_class.new(ProductsIndex::City).delete_all + Chewy.client.indices.refresh(index: 'products') + end.to change { described_class.new(ProductsIndex).total }.from(9).to(6) + end + + specify do + outer_payload = nil + ActiveSupport::Notifications.subscribe('delete_query.chewy') do |_name, _start, _finish, _id, payload| + outer_payload = payload + end + subject.query(match: {name: 'name3'}).delete_all + expect(outer_payload).to eq( + index: ProductsIndex, + indexes: [ProductsIndex], + request: {index: ['products'], type: %w[product city country], body: {query: {match: {name: 'name3'}}}}, + type: [ProductsIndex::Product, ProductsIndex::City, ProductsIndex::Country], + types: [ProductsIndex::Product, ProductsIndex::City, ProductsIndex::Country] + ) + end + end + end end