活动模型序列化程序属性上的嵌套查询

问题描述

我有两个模型,艺术品和事件,艺术品有很多事件。 一些事件已确认。

在我的序列化器中,我想返回每件艺术品的上次确认事件

现在可以了,但是还会创建一个慢速(n + 1?)查询,其中每个序列化的Artwork都会获取所有事件。

我该如何更快地做某事?


# artwork_controller.rb
      def index
        @artworks = Artwork.all
        render json: @artworks
      end

# artwork_serializer.rb
      attributes :id,:name,:photo,:created_at

      has_one :event do
        object.events.confirmed.last
      end

和日志

Processing by Api::V1::ArtworksController#index as JSON
  Passenger Load (2.0ms)  SELECT "artworks".* FROM "artworks"
  ↳ app/controllers/api/v1/artworks_controller.rb:11
[active_model_serializers]   Event Load (1.2ms)  SELECT  "events".* FROM "events" WHERE "events"."artwork_id" = $1 AND "events"."published" = $2 ORDER BY "events"."created_at" DESC LIMIT $3  [["artwork_id",16],["published",true],["LIMIT",1]]
[active_model_serializers]   ↳ app/serializers/api/v1/artwork_serializer.rb:9
[active_model_serializers]   Event Load (0.8ms)  SELECT  "events".* FROM "events" WHERE "events"."artwork_id" = $1 AND "events"."published" = $2 ORDER BY "events"."created_at" DESC LIMIT $3  [["artwork_id",9],1]]
[active_model_serializers]   ↳ app/serializers/api/v1/artwork_serializer.rb:9
[active_model_serializers]   Event Load (2.1ms)  SELECT  "events".* FROM "events" WHERE "events"."artwork_id" = $1 AND "events"."published" = $2 ORDER BY "events"."created_at" DESC LIMIT $3  [["artwork_id",27],1]]
[active_model_serializers]   ↳ app/serializers/api/v1/artwork_serializer.rb:9#
# ... for each artwork

[active_model_serializers]   ↳ app/serializers/api/v1/artwork_serializer.rb:9
[active_model_serializers]   User Load (1.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id",84],1]]
[active_model_serializers]   ↳ app/serializers/api/v1/event_serializer.rb:9
[active_model_serializers]   CACHE Event Load (0.0ms)  SELECT  "events".* FROM "events" WHERE "events"."artwork_id" = $1 AND "events"."published" = $2 ORDER BY "events"."created_at" DESC LIMIT $3  [["artwork_id",1]]
[active_model_serializers]   ↳ app/serializers/api/v1/artwork_serializer.rb:9
[active_model_serializers]   User Load (0.6ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id",88],1]]
[active_model_serializers]   ↳ app/serializers/api/v1/artwork_serializer.rb:9
[active_model_serializers]   User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id",76],11],1]]
# ... for each artwork events

解决方法

您可以尝试以下操作:

请将此关联添加到artwork模型中。

# app/models/artwork.rb

has_one :last_confirmed_event,-> { order(created_at: :desc).where(confirmed: true) },class_name: "Event"

在您的artworks控制器中添加eager-loading。

# app/controllers/artwork_controllers.rb

def index 
  @artworks = Artwork.all.includes(:last_confirmed_event)
  render json: @artworks 
end

在序列化器中最后一次使用时声明的关联。

# app/serializers/artwork_serializer.rb

attributes :id,:name,:photo,:created_at

has_one :last_confirmed_event

您可以根据需要更改关联名称。