Save Image in Elasticsearch with Ruby

2019-06-04 16:39发布

问题:

I'm using Elasticsearch as a datastore for my Ruby/Sinatra app, and I'm wanting to save images. Is there a way to index an image as a binary into ES? If so, how should I go about doing this and then converting the binary back to an image in order to display it on the site?

回答1:

Elasticsearch can store binary data using the binary type. The binary type needs to be base64 encoded and will not be indexed by default. Here is an example es mapping

POST http://localhost:9200/adimages/
{
    "mappings" : {
    "images" : {
        "properties" : {
            "image" : { "type" : "binary"},
            "id" : {"type" : "string"}
        }
    }
}

Some sinatra/ruby code

  get '/pictures/:name' do |name|                                                                                                                                                    
    @image = @es_client.search index: 'adsimages', body: { query: { match: { id: name } } }   
    @image = AdHelpers.get_hashie_list(@image)
    content_type 'image/png' #hardcoded content type for now
    fileContent = Base64.decode64(@image[0].image);
  end 

  post '/sell/pictures' do
    #adsimagesindex/images
    image_id = SecureRandom.hex
    file = params[:file][:tempfile] #get the post from body
    fileContent = file.read
    fileContent =  Base64.encode64(fileContent)
    @es_client.index index: 'adsimages', type: 'images', id: image_id, body: {id: image_id, image: fileContent}
    redirect '/ads/sell/pictures' 
  end 

You then use a form to submit the image

<form class="form-horizontal" action="/ads/sell/pictures" method="post">
    <div class="container"> 
      <div class="form-group">
        <label for="upload-pictures">Upload Pictures</label>
        <input type="file" id="file" name="upload-pictures[]" multiple>
      </div>

      <button type="submit" class="btn btn-default">Next</button>
    </div>
</form>

to retrieve the image do 'GET /ads/sell/pictures/7a911a0355ad1cc3cfc78bbf6038699b'

If you want to store images along with the your documents (depending on your use case) you can omit the image field when doing the search by specifying the fields you want returned back. Alternatively you can just store the image id(s) with your documents and create an index only for images.

Hope this helps!