stretcher 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +1 -0
- data/lib/stretcher/es_component.rb +2 -3
- data/lib/stretcher/index.rb +27 -9
- data/lib/stretcher/index_type.rb +12 -25
- data/lib/stretcher/server.rb +31 -31
- data/lib/stretcher/util.rb +22 -0
- data/lib/stretcher/version.rb +1 -1
- data/spec/lib/stretcher_index_spec.rb +86 -12
- data/spec/lib/stretcher_index_type_spec.rb +51 -23
- data/spec/lib/stretcher_server_spec.rb +8 -3
- data/spec/spec_helper.rb +1 -0
- metadata +2 -2
    
        data/README.md
    CHANGED
    
    
| @@ -17,7 +17,6 @@ module Stretcher | |
| 17 17 | 
             
                    body = generic_opts
         | 
| 18 18 | 
             
                  end
         | 
| 19 19 |  | 
| 20 | 
            -
                  logger.info { "Stretcher Search: curl -XGET '#{Util.qurl(path_uri('_search'), query_opts)}' -d '#{body.to_json}'" }
         | 
| 21 20 | 
             
                  response = request(:get, "_search", query_opts) do |req|
         | 
| 22 21 | 
             
                    req.body = body
         | 
| 23 22 | 
             
                  end
         | 
| @@ -28,10 +27,10 @@ module Stretcher | |
| 28 27 | 
             
                  request(:post, "_refresh")
         | 
| 29 28 | 
             
                end
         | 
| 30 29 |  | 
| 31 | 
            -
                def request(method, path=nil,  | 
| 30 | 
            +
                def request(method, path=nil, params={}, body=nil, headers={}, &block)
         | 
| 32 31 | 
             
                  prefixed_path = path_uri(path)
         | 
| 33 32 | 
             
                  raise "Cannot issue request, no server specified!" unless @server
         | 
| 34 | 
            -
                  @server.request(method, prefixed_path,  | 
| 33 | 
            +
                  @server.request(method, prefixed_path, params, body, headers, &block)
         | 
| 35 34 | 
             
                end
         | 
| 36 35 |  | 
| 37 36 | 
             
                def do_delete_query(query)
         | 
    
        data/lib/stretcher/index.rb
    CHANGED
    
    | @@ -26,21 +26,39 @@ module Stretcher | |
| 26 26 | 
             
                #
         | 
| 27 27 | 
             
                #    docs = [{"_type" => "tweet", "_id" => 91011, "text" => "Bulked"}]
         | 
| 28 28 | 
             
                #    server.index(:foo).bulk_index(docs)
         | 
| 29 | 
            -
                def bulk_index(documents)
         | 
| 30 | 
            -
                   | 
| 29 | 
            +
                def bulk_index(documents, options={})
         | 
| 30 | 
            +
                  bulk_action(:index, documents, options)
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                # Given a hash of documents, will bulk delete
         | 
| 34 | 
            +
                #
         | 
| 35 | 
            +
                #    docs = [{"_type" => "tweet", "_id" => 91011}]
         | 
| 36 | 
            +
                #    server.index(:foo).bulk_delete(docs)
         | 
| 37 | 
            +
                def bulk_delete(documents, options={})
         | 
| 38 | 
            +
                  bulk_action(:delete, documents, options)
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def bulk_action(action, documents, options={})
         | 
| 42 | 
            +
                  action=action.to_sym
         | 
| 43 | 
            +
                  
         | 
| 44 | 
            +
                  body = documents.reduce("") {|post_data, d_raw|
         | 
| 31 45 | 
             
                    d = Hashie::Mash.new(d_raw)
         | 
| 32 | 
            -
                     | 
| 33 | 
            -
                     | 
| 34 | 
            -
                     | 
| 35 | 
            -
             | 
| 46 | 
            +
                    index_meta = { :_index => name, :_id => (d.delete(:id) || d.delete(:_id)) }
         | 
| 47 | 
            +
                    
         | 
| 48 | 
            +
                    d.keys.reduce(index_meta) do |memo, key|
         | 
| 49 | 
            +
                      index_meta[key] = d.delete(key) if key.to_s.start_with?('_')
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    post_data << ({action => index_meta}.to_json + "\n")
         | 
| 53 | 
            +
                    post_data << (d.to_json + "\n") unless action == :delete
         | 
| 54 | 
            +
                    post_data
         | 
| 36 55 | 
             
                  }
         | 
| 56 | 
            +
                  @server.bulk body, options
         | 
| 37 57 | 
             
                end
         | 
| 38 58 |  | 
| 39 59 | 
             
                # Creates the index, with the supplied hash as the optinos body (usually mappings: and settings:))
         | 
| 40 60 | 
             
                def create(options={})
         | 
| 41 | 
            -
                  request(:put | 
| 42 | 
            -
                    req.body = options
         | 
| 43 | 
            -
                  end
         | 
| 61 | 
            +
                  request(:put, "/", {}, options)
         | 
| 44 62 | 
             
                end
         | 
| 45 63 |  | 
| 46 64 | 
             
                # Deletes the index
         | 
    
        data/lib/stretcher/index_type.rb
    CHANGED
    
    | @@ -26,40 +26,29 @@ module Stretcher | |
| 26 26 | 
             
                    options = {}
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 |  | 
| 29 | 
            -
                  # If fields is passed in as an array, properly encode it
         | 
| 30 | 
            -
                  arg_fields = options[:fields]
         | 
| 31 | 
            -
                  if arg_fields.is_a?(Array)
         | 
| 32 | 
            -
                    # no #merge! we don't want to mutate args
         | 
| 33 | 
            -
                    options = options.merge(:fields => arg_fields.join(","))
         | 
| 34 | 
            -
                  end
         | 
| 35 | 
            -
                  
         | 
| 36 29 | 
             
                  res = request(:get, id, options)
         | 
| 37 30 | 
             
                  raw ? res : (res["_source"] || res["fields"])
         | 
| 38 31 | 
             
                end
         | 
| 39 32 |  | 
| 40 33 | 
             
                # Retrieves multiple documents of the index type by ID
         | 
| 41 34 | 
             
                # http://www.elasticsearch.org/guide/reference/api/multi-get/
         | 
| 42 | 
            -
                def mget(ids)
         | 
| 43 | 
            -
                  request(:get, '_mget' | 
| 44 | 
            -
                    req.body = { :ids => ids }
         | 
| 45 | 
            -
                  end
         | 
| 35 | 
            +
                def mget(ids, options={})
         | 
| 36 | 
            +
                  request(:get, '_mget', options, :ids => ids)
         | 
| 46 37 | 
             
                end
         | 
| 47 38 |  | 
| 48 39 | 
             
                # Explains a query for a specific document
         | 
| 49 | 
            -
                def explain(id, query)
         | 
| 50 | 
            -
                  request(:get, "#{id}/_explain" | 
| 51 | 
            -
                    req.body = query
         | 
| 52 | 
            -
                  end
         | 
| 40 | 
            +
                def explain(id, query, options={})
         | 
| 41 | 
            +
                  request(:get, "#{id}/_explain", options, query)
         | 
| 53 42 | 
             
                end
         | 
| 54 43 |  | 
| 55 44 | 
             
                # Index an item with a specific ID
         | 
| 56 | 
            -
                def put(id, source)
         | 
| 57 | 
            -
                  request(:put, id, source)
         | 
| 45 | 
            +
                def put(id, source, options={})
         | 
| 46 | 
            +
                  request(:put, id, options, source)
         | 
| 58 47 | 
             
                end
         | 
| 59 48 |  | 
| 60 49 | 
             
                # Index an item with automatic ID generation
         | 
| 61 | 
            -
                def post(source)
         | 
| 62 | 
            -
                  request(:post, nil, source)
         | 
| 50 | 
            +
                def post(source, options={})
         | 
| 51 | 
            +
                  request(:post, nil, options, source)
         | 
| 63 52 | 
             
                end
         | 
| 64 53 |  | 
| 65 54 | 
             
                # Uses the update api to modify a document with a script
         | 
| @@ -69,12 +58,12 @@ module Stretcher | |
| 69 58 | 
             
                # Takes an optional, third options hash, allowing you to specify
         | 
| 70 59 | 
             
                # Additional query parameters such as +fields+ and +routing+
         | 
| 71 60 | 
             
                def update(id, body, options={})
         | 
| 72 | 
            -
                  request(:post,  | 
| 61 | 
            +
                  request(:post, "#{id}/_update", options, body)
         | 
| 73 62 | 
             
                end
         | 
| 74 63 |  | 
| 75 64 | 
             
                # Deletes the document with the given ID
         | 
| 76 | 
            -
                def delete(id)
         | 
| 77 | 
            -
                  request :delete, id
         | 
| 65 | 
            +
                def delete(id, options={})
         | 
| 66 | 
            +
                  request :delete, id, options
         | 
| 78 67 | 
             
                rescue Stretcher::RequestError => e
         | 
| 79 68 | 
             
                  raise e if e.http_response.status != 404
         | 
| 80 69 | 
             
                  false
         | 
| @@ -94,9 +83,7 @@ module Stretcher | |
| 94 83 |  | 
| 95 84 | 
             
                # Alter the mapping for this type
         | 
| 96 85 | 
             
                def put_mapping(body)
         | 
| 97 | 
            -
                  request(:put, "_mapping" | 
| 98 | 
            -
                    req.body = body
         | 
| 99 | 
            -
                  }
         | 
| 86 | 
            +
                  request(:put, "_mapping", {}, body)
         | 
| 100 87 | 
             
                end
         | 
| 101 88 |  | 
| 102 89 | 
             
                # Check if this index type is defined, if passed an id
         | 
    
        data/lib/stretcher/server.rb
    CHANGED
    
    | @@ -11,8 +11,8 @@ module Stretcher | |
| 11 11 |  | 
| 12 12 | 
             
                    builder.request :json
         | 
| 13 13 |  | 
| 14 | 
            -
                    builder.options[:read_timeout] =  | 
| 15 | 
            -
                    builder.options[:open_timeout] =  | 
| 14 | 
            +
                    builder.options[:read_timeout] = options[:read_timeout] || 4
         | 
| 15 | 
            +
                    builder.options[:open_timeout] = options[:open_timeout] || 2
         | 
| 16 16 |  | 
| 17 17 | 
             
                    if faraday_configurator = options[:faraday_configurator]
         | 
| 18 18 | 
             
                      faraday_configurator.call(builder)
         | 
| @@ -20,6 +20,11 @@ module Stretcher | |
| 20 20 | 
             
                      builder.adapter :excon
         | 
| 21 21 | 
             
                    end
         | 
| 22 22 | 
             
                  end
         | 
| 23 | 
            +
                  http.headers = {
         | 
| 24 | 
            +
                    :accept =>  'application/json',
         | 
| 25 | 
            +
                    :user_agent => "Stretcher Ruby Gem #{Stretcher::VERSION}",
         | 
| 26 | 
            +
                    "Content-Type" => "application/json"
         | 
| 27 | 
            +
                  }
         | 
| 23 28 |  | 
| 24 29 | 
             
                  uri_components = URI.parse(uri)
         | 
| 25 30 | 
             
                  if uri_components.user || uri_components.password
         | 
| @@ -90,10 +95,8 @@ module Stretcher | |
| 90 95 |  | 
| 91 96 | 
             
                # Perform a raw bulk operation. You probably want to use Stretcher::Index#bulk_index
         | 
| 92 97 | 
             
                # which properly formats a bulk index request.
         | 
| 93 | 
            -
                def bulk(data)
         | 
| 94 | 
            -
                  request(:post, path_uri("/_bulk") | 
| 95 | 
            -
                    req.body = data
         | 
| 96 | 
            -
                  end
         | 
| 98 | 
            +
                def bulk(data, options={})
         | 
| 99 | 
            +
                  request(:post, path_uri("/_bulk"), options, data)
         | 
| 97 100 | 
             
                end
         | 
| 98 101 |  | 
| 99 102 | 
             
                # Retrieves stats for this server
         | 
| @@ -125,12 +128,10 @@ module Stretcher | |
| 125 128 | 
             
                def msearch(body=[])
         | 
| 126 129 | 
             
                  raise ArgumentError, "msearch takes an array!" unless body.is_a?(Array)
         | 
| 127 130 | 
             
                  fmt_body = body.map(&:to_json).join("\n") + "\n"
         | 
| 128 | 
            -
                   | 
| 129 | 
            -
                  res = request(:get, path_uri("/_msearch") | 
| 130 | 
            -
                    req.body = fmt_body
         | 
| 131 | 
            -
                  }
         | 
| 131 | 
            +
                  
         | 
| 132 | 
            +
                  res = request(:get, path_uri("/_msearch"), {}, fmt_body)
         | 
| 132 133 |  | 
| 133 | 
            -
                  errors = res.responses. | 
| 134 | 
            +
                  errors = res.responses.map(&:error).compact
         | 
| 134 135 | 
             
                  if !errors.empty?
         | 
| 135 136 | 
             
                    raise RequestError.new(res), "Could not msearch #{errors.inspect}"
         | 
| 136 137 | 
             
                  end
         | 
| @@ -163,9 +164,7 @@ module Stretcher | |
| 163 164 | 
             
                # as per: http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html
         | 
| 164 165 | 
             
                def aliases(body=nil)
         | 
| 165 166 | 
             
                  if body
         | 
| 166 | 
            -
                    request(:post, path_uri("/_aliases") | 
| 167 | 
            -
                      req.body = body
         | 
| 168 | 
            -
                    end
         | 
| 167 | 
            +
                    request(:post, path_uri("/_aliases"), {}, body)
         | 
| 169 168 | 
             
                  else
         | 
| 170 169 | 
             
                    request(:get, path_uri("/_aliases"))
         | 
| 171 170 | 
             
                  end
         | 
| @@ -182,24 +181,25 @@ module Stretcher | |
| 182 181 | 
             
                end
         | 
| 183 182 |  | 
| 184 183 | 
             
                # Handy way to query the server, returning *only* the body
         | 
| 185 | 
            -
                # Will raise an exception when the status is not in the 2xx range
         | 
| 186 | 
            -
                def request(method,  | 
| 187 | 
            -
                   | 
| 188 | 
            -
                  
         | 
| 189 | 
            -
                   | 
| 190 | 
            -
                   | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
                     | 
| 198 | 
            -
             | 
| 199 | 
            -
                    end
         | 
| 200 | 
            -
                  })
         | 
| 184 | 
            +
                # Will raise an exception when the status is not in the 2xx range    
         | 
| 185 | 
            +
                def request(method, path, params={}, body=nil, headers={}, &block)
         | 
| 186 | 
            +
                  req = http.build_request(method)
         | 
| 187 | 
            +
                  req.path = path
         | 
| 188 | 
            +
                  req.params.update(Util.clean_params(params)) if params
         | 
| 189 | 
            +
                  req.body = body if body
         | 
| 190 | 
            +
                  req.headers.update(headers) if headers
         | 
| 191 | 
            +
                  block.call(req) if block
         | 
| 192 | 
            +
                  logger.debug { Util.curl_format(req) }
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                  @request_mtx.synchronize {
         | 
| 195 | 
            +
                    env = req.to_env(http)
         | 
| 196 | 
            +
                    check_response(http.app.call(env))
         | 
| 197 | 
            +
                  }
         | 
| 201 198 | 
             
                end
         | 
| 202 | 
            -
             | 
| 199 | 
            +
             | 
| 200 | 
            +
                private
         | 
| 201 | 
            +
             | 
| 202 | 
            +
             | 
| 203 203 | 
             
                # Internal use only
         | 
| 204 204 | 
             
                # Check response codes from request
         | 
| 205 205 | 
             
                def check_response(res)
         | 
    
        data/lib/stretcher/util.rb
    CHANGED
    
    | @@ -1,5 +1,17 @@ | |
| 1 1 | 
             
            module Stretcher
         | 
| 2 2 | 
             
              module Util
         | 
| 3 | 
            +
                
         | 
| 4 | 
            +
                # cURL formats a Faraday req. Useful for logging
         | 
| 5 | 
            +
                def self.curl_format(req)
         | 
| 6 | 
            +
                  body = "-d '#{req.body.is_a?(Hash) ? req.body.to_json : req.body}'" if req.body
         | 
| 7 | 
            +
                  headers = req.headers.map {|name, value| "'-H #{name}: #{value}'" }.sort.join(' ')
         | 
| 8 | 
            +
                  method = req.method.to_s.upcase
         | 
| 9 | 
            +
                  url = Util.qurl(req.path,req.params)
         | 
| 10 | 
            +
                  
         | 
| 11 | 
            +
                  ["curl -X#{method}", url, body, headers].compact.join(' ')  
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                # Formats a url + query opts
         | 
| 3 15 | 
             
                def self.qurl(url, query_opts=nil)
         | 
| 4 16 | 
             
                  query_opts && !query_opts.empty? ? "#{url}?#{querify(query_opts)}" : url
         | 
| 5 17 | 
             
                end
         | 
| @@ -7,5 +19,15 @@ module Stretcher | |
| 7 19 | 
             
                def self.querify(hash)
         | 
| 8 20 | 
             
                  hash.map {|k,v| "#{k}=#{v}"}.join('&')
         | 
| 9 21 | 
             
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def self.clean_params params={}
         | 
| 24 | 
            +
                  return unless params
         | 
| 25 | 
            +
                  clean_params = {}
         | 
| 26 | 
            +
                  params.each do |key, value|
         | 
| 27 | 
            +
                    clean_params[key] = value.is_a?(Array) ? value.join(',') : value
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  clean_params
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 10 32 | 
             
              end
         | 
| 11 33 | 
             
            end
         | 
    
        data/lib/stretcher/version.rb
    CHANGED
    
    
| @@ -11,7 +11,12 @@ describe Stretcher::Index do | |
| 11 11 | 
             
                rescue Stretcher::RequestError::NotFound
         | 
| 12 12 | 
             
                end
         | 
| 13 13 | 
             
                server.refresh
         | 
| 14 | 
            -
                i.create
         | 
| 14 | 
            +
                i.create({
         | 
| 15 | 
            +
                  :settings => {
         | 
| 16 | 
            +
                    :number_of_shards => 1,
         | 
| 17 | 
            +
                    :number_of_replicas => 0
         | 
| 18 | 
            +
                  }
         | 
| 19 | 
            +
                })
         | 
| 15 20 | 
             
                # Why do both? Doesn't hurt, and it fixes some races
         | 
| 16 21 | 
             
                server.refresh
         | 
| 17 22 | 
             
                i.refresh
         | 
| @@ -66,14 +71,57 @@ describe Stretcher::Index do | |
| 66 71 | 
             
              end
         | 
| 67 72 |  | 
| 68 73 | 
             
              it "should retrieve settings properly" do
         | 
| 69 | 
            -
                index.get_settings['foo']['settings']['index. | 
| 74 | 
            +
                index.get_settings['foo']['settings']['index.number_of_shards'].should eq("1")
         | 
| 75 | 
            +
                index.get_settings['foo']['settings']['index.number_of_replicas'].should eq("0")
         | 
| 70 76 | 
             
              end
         | 
| 71 77 |  | 
| 72 | 
            -
               | 
| 73 | 
            -
                 | 
| 74 | 
            -
             | 
| 75 | 
            -
                   | 
| 76 | 
            -
             | 
| 78 | 
            +
              describe "bulk operations" do
         | 
| 79 | 
            +
                it "should bulk index documents properly" do
         | 
| 80 | 
            +
                  seed_corpus
         | 
| 81 | 
            +
                  corpus.each {|doc|
         | 
| 82 | 
            +
                    fetched_doc = index.type(doc["_type"]).get(doc["_id"] || doc["id"], {}, true)
         | 
| 83 | 
            +
                    fetched_doc._source.text.should == doc[:text]
         | 
| 84 | 
            +
                    fetched_doc._source._id.should be_nil
         | 
| 85 | 
            +
                    fetched_doc._source._type.should be_nil
         | 
| 86 | 
            +
                  }
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                it "should bulk delete documents" do
         | 
| 90 | 
            +
                  seed_corpus
         | 
| 91 | 
            +
                  index.bulk_delete([
         | 
| 92 | 
            +
                                     {"_type" => 'tweet', "_id" => 'fooid'},
         | 
| 93 | 
            +
                                     {"_type" => 'tweet', "_id" => 'barid'},
         | 
| 94 | 
            +
                                    ])
         | 
| 95 | 
            +
                  index.refresh
         | 
| 96 | 
            +
                  res = index.search({}, {:query => {:match_all => {}}})
         | 
| 97 | 
            +
                  expect(res.results.map(&:_id)).to match_array ['bazid']
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
              it 'allows _routing to be set on bulk index documents' do
         | 
| 102 | 
            +
                server.index(:with_routing).delete if server.index(:with_routing).exists?
         | 
| 103 | 
            +
                server.index(:with_routing).create({
         | 
| 104 | 
            +
                  :settings => {
         | 
| 105 | 
            +
                    :number_of_shards => 1,
         | 
| 106 | 
            +
                    :number_of_replicas => 0
         | 
| 107 | 
            +
                  },
         | 
| 108 | 
            +
                  :mappings => {
         | 
| 109 | 
            +
                    :_default_ =>  {
         | 
| 110 | 
            +
                      :_routing => { :required => true }
         | 
| 111 | 
            +
                    }
         | 
| 112 | 
            +
                  }
         | 
| 113 | 
            +
                })
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                lambda {server.index(:with_routing).bulk_index(corpus)}.should raise_exception
         | 
| 116 | 
            +
                routed_corpus = corpus.map do |doc|
         | 
| 117 | 
            +
                  routed_doc = doc.clone
         | 
| 118 | 
            +
                  routed_doc['_routing'] = 'abc'
         | 
| 119 | 
            +
                  routed_doc
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                server.index(:with_routing).bulk_index(routed_corpus)
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                server.index(:with_routing).delete
         | 
| 77 125 | 
             
              end
         | 
| 78 126 |  | 
| 79 127 | 
             
              it "should delete by query" do
         | 
| @@ -93,11 +141,37 @@ describe Stretcher::Index do | |
| 93 141 | 
             
              end
         | 
| 94 142 |  | 
| 95 143 | 
             
              # TODO: Actually use two indexes
         | 
| 96 | 
            -
               | 
| 97 | 
            -
                 | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 144 | 
            +
              describe "msearch" do
         | 
| 145 | 
            +
                let(:res) {
         | 
| 146 | 
            +
                  seed_corpus
         | 
| 147 | 
            +
                  q2_text = corpus.first[:text]
         | 
| 148 | 
            +
                  queries = [
         | 
| 149 | 
            +
                             {:query => {:match_all => {}}},
         | 
| 150 | 
            +
                             {:query => {:match => {:text => q2_text}}}
         | 
| 151 | 
            +
                            ]
         | 
| 152 | 
            +
                  index.msearch(queries)
         | 
| 153 | 
            +
                }
         | 
| 154 | 
            +
                
         | 
| 155 | 
            +
                it "should return an array of Stretcher::SearchResults" do
         | 
| 156 | 
            +
                  res.length.should == 2
         | 
| 157 | 
            +
                  res[0].class.should == Stretcher::SearchResults
         | 
| 158 | 
            +
                end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                it "should return the query results in order" do
         | 
| 161 | 
            +
                  # First query returns all docs, second only one
         | 
| 162 | 
            +
                  res[0].results.length.should == corpus.length
         | 
| 163 | 
            +
                  res[1].results.length.should == 1
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                it "should raise an error if any query is bad" do
         | 
| 167 | 
            +
                  queries = [
         | 
| 168 | 
            +
                             {:query => {:match_all => {}}},
         | 
| 169 | 
            +
                             {:query => {:invalid_query => {}}}
         | 
| 170 | 
            +
                            ]
         | 
| 171 | 
            +
                  expect {
         | 
| 172 | 
            +
                    index.msearch(queries)
         | 
| 173 | 
            +
                  }.to raise_error(Stretcher::RequestError)
         | 
| 174 | 
            +
                end
         | 
| 101 175 | 
             
              end
         | 
| 102 176 |  | 
| 103 177 | 
             
              it "execute the analysis API and return an expected result" do
         | 
| @@ -1,19 +1,10 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe Stretcher::IndexType do
         | 
| 4 | 
            -
              let(:server) { Stretcher::Server.new(ES_URL) }
         | 
| 5 | 
            -
              let(:index) {
         | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
              }
         | 
| 9 | 
            -
              let(:type) {
         | 
| 10 | 
            -
                t = index.type(:bar)
         | 
| 11 | 
            -
                t.delete_query(:match_all => {})
         | 
| 12 | 
            -
                index.refresh
         | 
| 13 | 
            -
                mapping = {"bar" => {"properties" => {"message" => {"type" => "string"}}}}
         | 
| 14 | 
            -
                t.put_mapping mapping
         | 
| 15 | 
            -
                t
         | 
| 16 | 
            -
              }
         | 
| 4 | 
            +
              let(:server) { Stretcher::Server.new(ES_URL, :logger => DEBUG_LOGGER) }
         | 
| 5 | 
            +
              let(:index) { server.index(:foo) }
         | 
| 6 | 
            +
              
         | 
| 7 | 
            +
              let(:type) {  index.type(:bar) }
         | 
| 17 8 |  | 
| 18 9 | 
             
              it "should be existentially aware" do
         | 
| 19 10 | 
             
                t = index.type(:existential)
         | 
| @@ -24,9 +15,16 @@ describe Stretcher::IndexType do | |
| 24 15 | 
             
                t.get_mapping.should == mapping
         | 
| 25 16 | 
             
              end
         | 
| 26 17 |  | 
| 18 | 
            +
              before do
         | 
| 19 | 
            +
                type.delete_query(:match_all => {})
         | 
| 20 | 
            +
                index.refresh
         | 
| 21 | 
            +
                type.put_mapping({"bar" => {"properties" => {"message" => {"type" => "string"}}}})
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 27 24 | 
             
              describe "searching" do
         | 
| 28 25 | 
             
                before do
         | 
| 29 26 | 
             
                  @doc = {:message => "hello"}
         | 
| 27 | 
            +
             | 
| 30 28 | 
             
                  type.put(123123, @doc)
         | 
| 31 29 | 
             
                  index.refresh
         | 
| 32 30 | 
             
                end
         | 
| @@ -67,6 +65,12 @@ describe Stretcher::IndexType do | |
| 67 65 | 
             
                  type.mget([988, 989]).docs.first._source.message.should == 'message one!'
         | 
| 68 66 | 
             
                  type.mget([988, 989]).docs.last._source.message.should == 'message two!'
         | 
| 69 67 | 
             
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                it 'allows options to be passed through' do
         | 
| 70 | 
            +
                  response = type.mget([988, 989], :fields => 'message')
         | 
| 71 | 
            +
                  response.docs.first.fields.message.should == 'message one!'
         | 
| 72 | 
            +
                  response.docs.last.fields.message.should == 'message two!'
         | 
| 73 | 
            +
                end
         | 
| 70 74 | 
             
              end
         | 
| 71 75 |  | 
| 72 76 | 
             
              describe "ops on individual docs" do
         | 
| @@ -76,12 +80,12 @@ describe Stretcher::IndexType do | |
| 76 80 | 
             
                end
         | 
| 77 81 |  | 
| 78 82 | 
             
                describe "put" do
         | 
| 79 | 
            -
                  it "should put correctly" do
         | 
| 80 | 
            -
                    @ | 
| 83 | 
            +
                  it "should put correctly, with options" do
         | 
| 84 | 
            +
                    type.put(987, @doc, :version_type => :external, :version => 42)._version.should == 42
         | 
| 81 85 | 
             
                  end
         | 
| 82 86 |  | 
| 83 | 
            -
                  it "should post correctly" do
         | 
| 84 | 
            -
                    type.post(@doc). | 
| 87 | 
            +
                  it "should post correctly, with options" do
         | 
| 88 | 
            +
                    type.post(@doc, :version_type => :external, :version => 42)._version.should == 42
         | 
| 85 89 | 
             
                  end
         | 
| 86 90 | 
             
                end
         | 
| 87 91 |  | 
| @@ -127,18 +131,35 @@ describe Stretcher::IndexType do | |
| 127 131 | 
             
                  end
         | 
| 128 132 | 
             
                end
         | 
| 129 133 |  | 
| 130 | 
            -
                 | 
| 131 | 
            -
                   | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 134 | 
            +
                describe 'explain' do
         | 
| 135 | 
            +
                  it "should explain a query" do
         | 
| 136 | 
            +
                    type.exists?(987).should be_true
         | 
| 137 | 
            +
                    index.refresh
         | 
| 138 | 
            +
                    res = type.explain(987, {:query => {:match_all => {}}})
         | 
| 139 | 
            +
                    res.should have_key('explanation')
         | 
| 140 | 
            +
                  end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  it 'should allow options to be passed through' do
         | 
| 143 | 
            +
                    index.refresh
         | 
| 144 | 
            +
                    type.explain(987, {:query => {:match_all => {}}}, {:fields => 'message'}).get.fields.message.should == 'hello!'
         | 
| 145 | 
            +
                  end
         | 
| 135 146 | 
             
                end
         | 
| 136 147 |  | 
| 137 | 
            -
                it "should update individual docs correctly" do
         | 
| 148 | 
            +
                it "should update individual docs correctly using ctx.source" do
         | 
| 138 149 | 
             
                  type.update(987, :script => "ctx._source.message = 'Updated!'")
         | 
| 139 150 | 
             
                  type.get(987).message.should == 'Updated!'
         | 
| 140 151 | 
             
                end
         | 
| 141 152 |  | 
| 153 | 
            +
                it "should update individual docs correctly using doc" do
         | 
| 154 | 
            +
                  type.update(987, :doc => {:message => 'Updated!'})
         | 
| 155 | 
            +
                  type.get(987).message.should == 'Updated!'
         | 
| 156 | 
            +
                end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                it "should update individual docs correctly using doc and fields" do
         | 
| 159 | 
            +
                  response =  type.update(987, {:doc => {:message => 'Updated!'}}, :fields => 'message')
         | 
| 160 | 
            +
                  response.get.fields.message.should == 'Updated!'      
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
             | 
| 142 163 | 
             
                it "should delete by query correctly" do
         | 
| 143 164 | 
             
                  type.delete_query("match_all" => {})
         | 
| 144 165 | 
             
                  index.refresh
         | 
| @@ -150,5 +171,12 @@ describe Stretcher::IndexType do | |
| 150 171 | 
             
                  type.delete(987)
         | 
| 151 172 | 
             
                  type.exists?(987).should be_false
         | 
| 152 173 | 
             
                end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                it "should allow params to be passed to delete" do
         | 
| 176 | 
            +
                  version = type.get(987, {},  true)._version
         | 
| 177 | 
            +
                  lambda { type.delete(987, :version => version + 1) }.should raise_exception
         | 
| 178 | 
            +
                  type.delete(987, :version => version)
         | 
| 179 | 
            +
                  type.exists?(987).should be_false
         | 
| 180 | 
            +
                end
         | 
| 153 181 | 
             
              end
         | 
| 154 182 | 
             
            end
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe Stretcher::Server do
         | 
| 4 | 
            -
              let(:server) { Stretcher::Server.new(ES_URL) }
         | 
| 4 | 
            +
              let(:server) { Stretcher::Server.new(ES_URL, :logger => DEBUG_LOGGER) }
         | 
| 5 5 |  | 
| 6 6 | 
             
              it "should initialize cleanly" do
         | 
| 7 7 | 
             
                server.class.should == Stretcher::Server
         | 
| @@ -38,8 +38,6 @@ describe Stretcher::Server do | |
| 38 38 | 
             
              end
         | 
| 39 39 |  | 
| 40 40 | 
             
              it "should perform alias operations properly" do
         | 
| 41 | 
            -
                # Tear down any leftovers from previous runs
         | 
| 42 | 
            -
                server.aliases(:actions => [{:remove => {:alias => :foo_alias}}]) if server.index(:foo_alias).exists?
         | 
| 43 41 | 
             
                server.index(:foo).delete if server.index(:foo).exists?
         | 
| 44 42 | 
             
                server.index(:foo).create
         | 
| 45 43 | 
             
                server.aliases(:actions => [{:add => {:index => :foo, :alias => :foo_alias}}])
         | 
| @@ -75,4 +73,11 @@ describe Stretcher::Server do | |
| 75 73 | 
             
                analyzed = server.analyze("Candles", :analyzer => :snowball)
         | 
| 76 74 | 
             
                analyzed.tokens.first.token.should == 'candl'
         | 
| 77 75 | 
             
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              it 'logs requests correctly' do
         | 
| 78 | 
            +
                server.logger.should_receive(:debug) do |&block|
         | 
| 79 | 
            +
                  block.call.should == %{curl -XGET http://localhost:9200/_analyze?analyzer=snowball -d 'Candles' '-H Accept: application/json' '-H Content-Type: application/json' '-H User-Agent: Stretcher Ruby Gem #{Stretcher::VERSION}'}
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
                server.analyze("Candles", :analyzer => :snowball)
         | 
| 82 | 
            +
              end
         | 
| 78 83 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: stretcher
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.14.0
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2013-06- | 
| 12 | 
            +
            date: 2013-06-13 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: faraday
         |