1

私は、RailsでJSON APIを構築しています。応答を高速化して検索できるように、Elasticsearchを使用したいと思います。Rails:elasticsearch-modelとactive_model_serializersを一緒に使うことはできますか?

私は最初のモデルのためにelasticsearch-rails Gemを実装したばかりで、コンソールからESを正しくクエリできます。

APIコンシューマーが結果を利用できるようにするため、たとえば/articles/index.json?q="blahへのGETリクエストでは、一致する記事をESから取得してJSONに従ってレンダリングします。 API標準。

これを達成するために、レールactive_model_serializers gemを使用できますか?私は、JSON:APIフォーマットが既に処理されているので(jbuilderとは対照的に)、要求しています。

EDIT:これを正しくインデックスがESでモデル

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を検索することが可能となる:私は次のように持っている私のモデルでは

:ここで私は、現時点で立っているのですインデックス。私は私のコントローラで :シリアライザで

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宝石からこのHashie :: Mashオブジェクトにラップされます。

+0

暗いところで撮影しないように、コードを少しだけ用意することもできます。しかし、あなたが達成したいのは、jbuilderで実現可能です –

+0

私はコードatmはありません。これはまったく実行可能かどうかを尋ねています。モデルにはelasticsearch-railsが実装されていて、active_model_serializersでJSONをレンダリングします。明らかにJbuilderが選択肢ですが、質問に記載されているように、JSON:API準拠のデータを各モデルごとに独自に作成する必要があります – coconup

答えて

2

DBからレコードをフェッチする必要なく、うまく動作するようになりました。

シリアライザ(おそらく、より良い検索結果を得るために、専用のものを作成する)::

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を構築することができますここでは、将来のGooglerのための完全なソリューションですこのガイドに記載されているように、Elasticsearchから直接データを提供するという追加の利点があります。

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

関連する問題