Home > Software engineering >  Import data from Mongo to Elasticsearch on Rails
Import data from Mongo to Elasticsearch on Rails

Time:01-24

I use MongoDB to store information about products. Every product has a title (string), description(string), etc

My Gemfile

ruby '3.1.0'
gem 'mongoid', '~> 7.3.0'
gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
gem 'mini_magick'
gem 'kaminari-mongoid'
gem 'shopify_api'
gem 'bson_ext', '~> 1.5.1'
gem "graphql"
gem 'graphiql-rails'
gem 'simple_enum', '~> 2.3.0' , require: 'simple_enum/mongoid'
gem 'fog-aws'
gem 'carrierwave-aws'
gem 'elasticsearch', '~> 7.0'
gem 'elasticsearch-model'
gem 'elasticsearch-rails'

gem 'rails', '~> 6.1.4', '>= 6.1.4.4'

In my project/app/models/product.rb file I have:

class Product

  include Elasticsearch::Model
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Timestamps::Created
  include Mongoid::Timestamps::Updated

  index_name "products-#{Rails.env}"
  settings index: { number_of_shards: 1 } do
    mappings dynamic: 'false' do
      indexes :title, analyzer: 'english'
      indexes :description_html, analyzer: 'english'
      indexes :vendor, analyzer: 'english'
      indexes :product_type, analyzer: 'english'
    end
  end

  field :title, type: String, default: ""
  field :description_html, type: String, default: ""
  field :vendor, type: String, default: ""
  field :product_type, type: String, default: ""

  def as_indexed_json
    as_json({only: [:title, :description_html, :product_type, :vendor]})
  end

end

My init file elastic.rb

require 'elasticsearch'

ENV['RAILS_ENV'] = "development" # Set to your desired Rails environment name
require '/var/www/supfoxyapi.com/api/config/environment.rb'

class SyncData
  def initialize
    
    config = {
      host: "http://localhost:9200/",
      transport_options: {
        request: { timeout: 5 }
      },
    }

    Elasticsearch::Model.client = Elasticsearch::Client.new(config)

    unless Product.__elasticsearch__.index_exists?
      Product.__elasticsearch__.create_index! force: true
    end

    Product.import

    puts Product.search('Droplet').count
  end
end

SyncData.new

My problem in this line Product.import

When i try to Import products i got error

    raise NotImplemented, "Method not implemented for default adapter"
    ^^^^^
    from /home/vertalm/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/elasticsearch-model-7.2.0/lib/elasticsearch/model/importing.rb:145:in `import'
    from /home/vertalm/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/elasticsearch-model-7.2.0/lib/elasticsearch/model.rb:115:in `import'
    from elastic.rb:17:in `initialize'
    from elastic.rb:23:in `new'
    from elastic.rb:23:in `<main>'

I spend half a day to find solution, but no luck.

BTW i don't use Active records at all

Any help?

CodePudding user response:

You need to add a transform method to tell elasticsearch how to store the information.

Example from the code comments

#    transform = lambda do |a|
#      {index: {_id: a.id, _parent: a.author_id, data: a.__elasticsearch__.as_indexed_json}}
#    end
#
#    Article.import transform: transform

And this is what Active Record uses

lambda { |model|  { index: { _id: model.id, data: model.__elasticsearch__.as_indexed_json } } }

elastic-rails already implements the adapter for Active Record but the default adapter is basically empty and raises the exception you posted.

  •  Tags:  
  • Related