diff --git a/.erdconfig b/.erdconfig
new file mode 100644
index 0000000000000000000000000000000000000000..6d077b17393fb5120fe8611219660aa374bb03c6
--- /dev/null
+++ b/.erdconfig
@@ -0,0 +1,19 @@
+attributes:
+  - content
+  - foreign_key
+  - inheritance
+disconnected: true
+filename: erd
+filetype: pdf
+indirect: true
+inheritance: true
+markup: true
+notation: bachman
+orientation: horizontal
+polymorphism: false
+sort: true
+warn: true
+title: PortalMEC
+exclude: null
+only: null
+prepend_primary: false
diff --git a/app/controllers/v1/search_controller.rb b/app/controllers/v1/search_controller.rb
index 2a1aabec64446e46cff50a1ce33c079d53976372..c581c0866d8f36a120e74c290218cd404a4e6e3a 100644
--- a/app/controllers/v1/search_controller.rb
+++ b/app/controllers/v1/search_controller.rb
@@ -1,36 +1,27 @@
 class V1::SearchController < ApplicationController
-
   before_action :set_search
 
   # GET v1/search
   # GET v1/search.json
   def index
-    begin
-      render json: ActiveModel::ArraySerializer.new(search_service.fetch), status: :ok
-    rescue => e
-      if e.message == "Invalid search"
-        render json: @search.errors, status: :bad_request
-      else
-        render nothing: true, status: :internal_server_error
-        puts e.message
-        puts e.backtrace
-      end
+    render json: ActiveModel::ArraySerializer.new(SearchService.search(@search, current_user)), status: :ok
+  rescue => e
+    if e.message == 'Invalid search'
+      render json: @search.errors, status: :bad_request
+    else
+      render nothing: true, status: :internal_server_error
     end
   end
 
   # GET v1/search/autocomplete
   # GET v1/search/autocomplete.json
   def autocomplete
-    begin
-      render json: ActiveModel::ArraySerializer.new(search_service.autocomplete), status: :ok
-    rescue => e
-      if e.message == "Invalid search"
-        render json: @search.errors, status: :bad_request
-      else
-        render nothing: true, status: :internal_server_error
-        puts e.message
-        puts e.backtrace
-      end
+    render json: ActiveModel::ArraySerializer.new(SearchService.autocomplete(@search, current_user)), status: :ok
+  rescue => e
+    if e.message == 'Invalid search'
+      render json: @search.errors, status: :bad_request
+    else
+      render nothing: true, status: :internal_server_error
     end
   end
 
@@ -39,9 +30,4 @@ class V1::SearchController < ApplicationController
   def set_search
     @search = Search.new(params)
   end
-
-  def search_service
-    @search_service ||= SearchService.new(@search, current_user)
-  end
-
-end
\ No newline at end of file
+end
diff --git a/app/models/search.rb b/app/models/search.rb
index 0c08b232047816be0d88781c4867f8e154634068..5f9dcf1fae8b7f66ac5edf293154ee82ff82b1a4 100644
--- a/app/models/search.rb
+++ b/app/models/search.rb
@@ -4,22 +4,22 @@ class Search
 
   validates_presence_of :query, :results_per_page, :order, :search_class
   validates_numericality_of :results_per_page, greater_than: 0
-  validates :search_class, inclusion: {in: %w(LearningObject Collection User)}
+  validates :search_class, inclusion: { in: %w(LearningObject Collection User) }
 
-  def initialize(params={})
-    super(defaults.merge(params.select { |key,value| self.respond_to? key }))
+  def initialize(params = {})
+    super(defaults.merge(params.select { |key, _value| respond_to? key }))
   end
 
   def learning_object?
-    @search_class == "LearningObject"
+    search_class == 'LearningObject'
   end
 
   def collection?
-    @search_class == "Collection"
+    search_class == 'Collection'
   end
 
   def user?
-    @search_class == "User"
+    search_class == 'User'
   end
 
   private
@@ -32,5 +32,4 @@ class Search
       results_per_page: 10
     }
   end
-
-end
\ No newline at end of file
+end
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 7a472ab7ee7c429ff6afee2f4bab7b2a438efc37..f5fa43b5a613e930ec42e349931e0210e91281f1 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -1,129 +1,16 @@
-class SearchService
-
-  attr_accessor :search
-
-  def initialize(search, user)
-    @search = search
-    @user = user
-  end
-
-  def fetch
-    validate
-    return search_learning_object if @search.learning_object?
-    return search_collection if @search.collection?
-    return search_user if @search.user?
-  end
-
-  def autocomplete
-    validate
-
-    params_hash = {}
-    get_thumbnail = nil
-    get_type = nil
-    if @search.learning_object?
-      params_hash = { where: {state: validate_object},
-        fields: ['name^10', 'description', 'author'] }
-      get_thumbnail = Proc.new { |obj| obj.default_thumbnail }
-      get_type = Proc.new { |obj| obj.object_type.try(:name) }
-
-    elsif @search.collection?
-      params_hash = { where: {privacy: "public"},
-        fields: ['name^10', 'description', 'owner'] }
-      get_thumbnail = Proc.new { |obj| "/assets/icons/collection" }
-      get_type = Proc.new { |obj| "Collection"}
-
-    else #User
-      params_hash = { fields: ['name'] }
-      get_thumbnail = Proc.new { |obj| obj.avatar.url(:thumb) }
-      get_type = Proc.new { |obj| "User" }
-    end
-
-    autocomplete_search(Object.const_get(@search.search_class), @search.query, params_hash, get_type, get_thumbnail)
+module SearchService
+  def self.search(search, user)
+    model = instance(search, user)
+    model.search.results
   end
 
-  private
-
-  def validate
-    raise "Invalid search" unless @search.valid?
-  end
-
-  def search_learning_object
-    LearningObject.search(@search.query, where: lo_where_hash, order: lo_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
-  end
-  
-  def search_collection
-    Collection.search(@search.query, where: {privacy: "public"}, order: col_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
+  def self.autocomplete(search, user)
+    model = instance(search, user)
+    model.autocomplete
   end
 
-  def search_user
-    User.search(@search.query, order: user_order_hash(@search.order), page: @search.page, per_page: @search.results_per_page).results
+  def self.instance(search, user)
+    raise 'Invalid search' unless search.valid?
+    "SearchService::#{search.search_class}".constantize.new(search, user)
   end
-
-  def autocomplete_search(search_class, query, params_hash={}, get_type, get_thumbnail)
-    response = []
-    search_params = { limit: 10, misspellings: { below: 5 } }
-    objs = search_class.search(query, search_params.merge(params_hash))    
-    objs.each do |obj|
-      hash = {}
-      hash["id"] = obj.id
-      hash["name"] = obj.name
-      hash["type"] = get_type.call(obj)
-      hash["thumbnail"] = get_thumbnail.call(obj)
-      response << hash
-    end
-    response
-  end
-
-  def lo_where_hash
-    hash = {}
-    hash[:tags] = @search.tags unless @search.tags.blank?
-    hash[:object_type] = @search.types unless @search.types.blank?
-    hash[:source] = @search.sources unless @search.sources.blank?
-    hash[:state] = validate_object
-    hash.blank? ? nil : hash
-  end
-
-  def lo_order_hash(order)
-    case order
-    when 'author'
-      { author: {order: :asc, unmapped_type: :string} }
-    when 'publicationasc'
-      { published_at: {order: :asc, unmapped_type: :timestamp} }
-    when 'publicationdesc'
-      { published_at: {order: :desc, unmapped_type: :timestamp} }
-    when 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-  def col_order_hash(order)
-    case order
-    when 'author'
-      { owner: {order: :asc, unmapped_type: :string} }
-    when 'publicationasc'
-      { created_at: {order: :asc, unmapped_type: :timestamp} }
-    when 'publicationdesc'
-      { created_at: {order: :desc, unmapped_type: :timestamp} }
-    when 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-  def user_order_hash(order)
-    if order == 'title'
-      { name: {order: :asc, unmapped_type: :string} }
-    else
-      { score: {order: :desc, unmapped_type: :integer} }
-    end
-  end
-
-  def validate_object
-    return 'published' unless !@user.nil? && @user.is_admin?
-    return ['published', 'suspended', 'draft']
-  end
-
-end
\ No newline at end of file
+end
diff --git a/app/services/search_service/collection.rb b/app/services/search_service/collection.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b5c17c3a36d1a4117b8939ae7347dec075c18c20
--- /dev/null
+++ b/app/services/search_service/collection.rb
@@ -0,0 +1,29 @@
+module SearchService
+  class Collection < Model
+    def search
+      ::Collection.search(@search.query, where: { privacy: 'public' }, order: order_hash, page: @search.page, per_page: @search.results_per_page)
+    end
+
+    def autocomplete
+      params = {  where: { privacy: 'public' },
+                  fields: ['name^10', 'description', 'owner'] }
+      result = ::Collection.search(@search.query, autocomplete_params.merge(params))
+
+      thumbnail = proc { |_obj| '/assets/icons/collection' }
+      type = proc { |_obj| 'Collection' }
+      autocomplete_render(result, type, thumbnail)
+    end
+
+    private
+
+    def order_hash
+      case @search.order
+      when 'author' then { owner: { order: :asc, unmapped_type: :string } }
+      when 'publicationasc' then { created_at: { order: :asc, unmapped_type: :timestamp } }
+      when 'publicationdesc' then { created_at: { order: :desc, unmapped_type: :timestamp } }
+      when 'title' then { name: { order: :asc, unmapped_type: :string } }
+      else { score: { order: :desc, unmapped_type: :integer } }
+      end
+    end
+  end
+end
diff --git a/app/services/search_service/learning_object.rb b/app/services/search_service/learning_object.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c53a300febdfb77160bf5eca942d6c0ccd4b7d58
--- /dev/null
+++ b/app/services/search_service/learning_object.rb
@@ -0,0 +1,43 @@
+module SearchService
+  class LearningObject < Model
+    def search
+      ::LearningObject.search(@search.query, where: where_hash, order: order_hash, page: @search.page, per_page: @search.results_per_page)
+    end
+
+    def autocomplete
+      params = {  where: { state: validate_object },
+                  fields: ['name^10', 'description', 'author'] }
+      result = ::LearningObject.search(@search.query, autocomplete_params.merge(params))
+
+      thumbnail = proc { |obj| obj.default_thumbnail }
+      type = proc { |obj| obj.object_type.try(:name) }
+      autocomplete_render(result, type, thumbnail)
+    end
+
+    private
+
+    def where_hash
+      hash = {}
+      hash[:tags] = @search.tags unless @search.tags.blank?
+      hash[:object_type] = @search.types unless @search.types.blank?
+      hash[:source] = @search.sources unless @search.sources.blank?
+      hash[:state] = validate_object
+      hash.blank? ? nil : hash
+    end
+
+    def order_hash
+      case @search.order
+      when 'author' then { author: { order: :asc, unmapped_type: :string } }
+      when 'publicationasc' then { published_at: { order: :asc, unmapped_type: :timestamp } }
+      when 'publicationdesc' then { published_at: { order: :desc, unmapped_type: :timestamp } }
+      when 'title' then { name: { order: :asc, unmapped_type: :string } }
+      else { score: { order: :desc, unmapped_type: :integer } }
+      end
+    end
+
+    def validate_object
+      return 'published' unless !@user.nil? && @user.is_admin?
+      %w(published suspended draft)
+    end
+  end
+end
diff --git a/app/services/search_service/model.rb b/app/services/search_service/model.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e1a0bbb6bf43da38383cbee5c0cbe577db8b0b7f
--- /dev/null
+++ b/app/services/search_service/model.rb
@@ -0,0 +1,35 @@
+module SearchService
+  class Model
+    def initialize(search, user)
+      raise 'Invalid search' unless search.valid?
+
+      @search = search
+      @user = user
+    end
+
+    def search
+      raise 'Must implement!'
+    end
+
+    def autocomplete
+      raise 'Must implement!'
+    end
+
+    private
+
+    def autocomplete_params
+      { limit: 10, misspellings: { below: 5 } }
+    end
+
+    def autocomplete_render(result, type, thumbnail)
+      result.map do |obj|
+        {
+          id: obj.id,
+          name: obj.name,
+          type: type.call(obj),
+          thumbnail: thumbnail.call(obj)
+        }
+      end
+    end
+  end
+end
diff --git a/app/services/search_service/user.rb b/app/services/search_service/user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c7ffef549acbdcc0fd80dfebaee0d5f14a2dff72
--- /dev/null
+++ b/app/services/search_service/user.rb
@@ -0,0 +1,22 @@
+module SearchService
+  class User < Model
+    def search
+      ::User.search(@search.query, order: order_hash, page: @search.page, per_page: @search.results_per_page)
+    end
+
+    def autocomplete
+      result = ::User.search(@search.query, autocomplete_params.merge(fields: ['name']))
+
+      thumbnail = proc { |obj| obj.avatar.url(:thumb) }
+      type = proc { |_obj| 'User' }
+      autocomplete_render(result, type, thumbnail)
+    end
+
+    private
+
+    def order_hash
+      return { name: { order: :asc, unmapped_type: :string } } if @search.order == 'title'
+      { score: { order: :desc, unmapped_type: :integer } }
+    end
+  end
+end
diff --git a/test/services/search_service_test.rb b/test/services/search_service_test.rb
index 3733c0418a7ca9acda375eff3cdd99e07d1af071..cd1407ba2b2dfae9ee9f448dec307e3ae412bc85 100644
--- a/test/services/search_service_test.rb
+++ b/test/services/search_service_test.rb
@@ -1,69 +1,66 @@
 require 'test_helper'
 
 class SearchServiceTest < ActiveSupport::TestCase
-
   test 'fetch learning object with all search params' do
     reindex LearningObject
 
-    service = SearchService.new(Search.new(los_complete_search), users(:john))
-    assert_equal [learning_objects(:search)], service.fetch
+    search = SearchService.search(Search.new(los_complete_search), users(:john))
+    assert_equal [learning_objects(:search)], search
   end
 
   test 'fetch all public collections' do
     reindex Collection
 
-    service = SearchService.new(Search.new(collections_search), users(:john))
-    assert_equal [collections(:ufpr)], service.fetch
+    search = SearchService.search(Search.new(collections_search), users(:john))
+    assert_equal [collections(:ufpr)], search
   end
 
   test 'fetch users named john' do
     reindex User
 
-    service = SearchService.new(Search.new(users_john_search), users(:john))
-    assert_equal [users(:john), users(:one)], service.fetch
+    search = SearchService.search(Search.new(users_john_search), users(:john))
+    assert_equal [users(:john), users(:one)], search
   end
 
   test 'autocomplete users named john' do
     reindex User
 
-    service = SearchService.new(Search.new(users_john), users(:john))
-    assert_equal users_autocomplete_hashes([users(:john),users(:one)]), service.autocomplete
+    search = SearchService.autocomplete(Search.new(users_john), users(:john))
+    assert_equal users_autocomplete_hashes([users(:john), users(:one)]), search
   end
 
   private
 
   def los_complete_search
-    default_params.merge({
-      :query => 'teste', 
-      :search_class => 'LearningObject', 
-      :tags => ['Matemática'],
-      :types => ['Imagem'], 
-      :sources => ['UFPR institution']
-    })
+    default_params.merge(
+      query: 'teste',
+      search_class: 'LearningObject',
+      tags: ['Matemática'],
+      types: ['Imagem'],
+      sources: ['UFPR institution']
+    )
   end
 
   def collections_search
-    default_params.merge({
-      :search_class => 'Collection'
-    })
+    default_params.merge(search_class: 'Collection')
   end
 
   def users_john_search
     default_params.merge(users_john)
   end
-  
+
   def users_john
     {
-      :query => 'John',
-      :search_class => 'User'
+      query: 'John',
+      search_class: 'User'
     }
   end
 
   def default_params
     {
-      :page => 1,
-      :results_per_page => 10,
-      :order => 'score'
+      page: 1,
+      results_per_page: 10,
+      order: 'score'
     }
   end
 
@@ -72,17 +69,14 @@ class SearchServiceTest < ActiveSupport::TestCase
     klass.searchkick_index.refresh
   end
 
-  def users_autocomplete_hashes(users=[])
-    hashes = []
-    users.each do |user|
-      hash = {}
-      hash["id"] = user.id
-      hash["name"] = user.name
-      hash["type"] = "User"
-      hash["thumbnail"] = user.avatar.url(:thumb)
-      hashes << hash
+  def users_autocomplete_hashes(users = [])
+    users.map do |user|
+      {
+        id: user.id,
+        name: user.name,
+        type: 'User',
+        thumbnail: user.avatar.url(:thumb)
+      }
     end
-    hashes
   end
-
-end
\ No newline at end of file
+end