【问题标题】:Rails: can I use elasticsearch-model and active_model_serializers together?Rails:我可以同时使用 elasticsearch-model 和 active_model_serializers 吗?
【发布时间】:2017-05-30 14:21:53
【问题描述】:

我正在 Rails 中构建 JSON API,我想使用 Elasticsearch 来加快响应速度并允许搜索。

我刚刚为我的第一个模型实现了 elasticsearch-rails Gem,我可以从控制台成功查询 ES。

现在我想向 API 消费者提供结果,例如,对 /articles/index.json?q="blah" 的 GET 请求将从 ES 检索匹配的文章并根据 JSON:API 呈现它们标准。

是否可以使用 rails active_model_serializers gem 来实现这一点?我问是因为(与 jbuilder 相比)JSON:API 格式已经得到处理。

编辑:这就是我现在的立场:

在我的模型中,我有以下内容:

require 'elasticsearch/rails'
require 'elasticsearch/model'
class Thing < ApplicationRecord
    validates :user_id, :active, :status, presence: true
    include Elasticsearch::Model
    include Elasticsearch::Model::Callbacks

    index_name Rails.application.class.parent_name.underscore
    document_type self.name.downcase

    settings index: { number_of_shards: 1, number_of_replicas: 1 } do 
        mapping dynamic: 'strict' do 
            indexes :id, type: :string
            indexes :user_id, type: :string
            indexes :active, type: :boolean
            indexes :status, type: :string
        end 
    end

    def as_indexed_json(options = nil)
      self.as_json({
        only: [:id, :user_id, :active, :status],
      })
    end

    def self.search(query) 
        __elasticsearch__.search( { 
            query: { 
                multi_match: { 
                    query: query, 
                    fields: ['id^5', 'user_id'] 
                } 
            }
        } )
    end
end

这可以正确索引 ES 中的模型,并可以搜索 ES 索引。 在我的控制器中,我有:

class ThingsController < ApplicationController
    def index
        things = Thing.search(params[:query]).results.map{|m| m._source}
        render json: things, each_serializer: ThingSerializer
    end
end

在序列化器中,目前如下:

class ThingSerializer < ActiveModel::Serializer
    attributes :id, :user_id, :active, :status
end

不幸的是,这会在视图中显示以下 JSON:

{"data":[{"id":"","type":"hashie-mashes","attributes":{"user-id":null,"active":null,"status":null}}]}

所以序列化程序没有正确解析结果,结果是从 ES gem 包装到这个 Hashie::Mash 对象中。

【问题讨论】:

  • 您最好提供一些代码,这样我们就不会在黑暗中开枪了。但是,您想要实现的目标可以通过 jbuilder 实现
  • 我没有代码 atm,我在问这是否可行。我在模型中实现了 elasticsearch-rails,我想通过 active_model_serializers 呈现 JSON。 Jbuilder 显然是替代方案,但正如问题中所述,我必须让每个模型的数据 JSON:API 都符合我自己的要求

标签: ruby-on-rails json ruby elasticsearch active-model-serializers


【解决方案1】:

我终于设法让它很好地工作,而无需从数据库中获取记录。以下是未来谷歌员工的完整解决方案:

序列化器(最好为搜索结果创建一个专用的):

class SearchableThingSerializer < ActiveModel::Serializer
  type 'things' # This needs to be overridden, otherwise it will print "hashie-mashes"
  attributes :id # For some reason the mapping below doesn't work with :id

  [:user_id, :active, :status].map{|a| attribute(a) {object[:_source][a]}}

  def id
    object[:_source].id
  end
end

控制器:

def index
  things = Thing.search(params[:query])
  render json: things, each_serializer: SearchableThingSerializer
end

使用它,您可以按照本指南中的说明构建 JSON API,并具有直接从 Elasticsearch 提供数据的额外好处:

https://www.simplify.ba/articles/2016/06/18/creating-rails5-api-only-application-following-jsonapi-specification/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-17
    • 2015-02-28
    • 2011-07-21
    • 2015-05-19
    • 2019-05-21
    • 2021-09-05
    • 2014-04-08
    • 2020-06-23
    相关资源
    最近更新 更多