ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 이 액티브 레코드 쿼리의 성능을 높이려고합니다. Ruby on Rails
    카테고리 없음 2020. 8. 16. 15:29

    질문

    안녕하세요, 저는 활성 레코드를 처음 사용했습니다. 여기에이 두 가지 맵 기능이 있으며 아래 쿼리를 만드는 데 더 나은 / 더 성능이 좋은 방법이 있는지 궁금합니다.

    현재 쿼리를 실행할 때 터미널에 수백 개의 줄이 표시되고 많은 사람들이 동시에 이러한 수렴을로드하면 많은 메모리가 필요할 수 있습니다.

    1 단계 는 모든 관련 대화를 얻는 것입니다.

    2 단계 는 해당 대화에 연결된 발신자, 수신자 및 메시지에 대한 모든 정보로 대화 해시를 만드는 것입니다.

    3 단계 는 이러한 모든 대화를 올바른 순서로 정렬하여 가장 최근 메시지가 맨 위에있는 대화에서 정렬합니다.

    편집 1 : Rails 버전 5.0.1

     def index
          i = 1
          @messages = []
          @user = User.find_by(email: params[:email])
          @message = Conversation.where("sender_id = ? OR recipient_id = ?", @user.id, @user.id)
          @message.map { |conversation|
            @messages << conversation if Message.where(conversation_id: conversation.id).count > 0
          }
    
    
    
          render json: @messages.map { |conversation|
            {
              date: conversation.messages.last.created_at,
              sender: User.find(conversation.sender_id),
              recipient: User.find(conversation.recipient_id),
              conversation: {
                id: conversation.id,
                messages: Message.where(conversation_id: conversation.id).sort_by{|e| e[:created_at]}.reverse.map {|message| {
                  sender: {
                    email: User.find(message.user_id).email,
                    first_name: User.find(message.user_id).first_name,
                    last_name: User.find(message.user_id).last_nam },
                  body: message.body,
                  created_at: message.created_at
                  }
                }
              }}
          }.sort_by { |hsh| hsh[:date] }.reverse
     end

    답변1

    class Message < ApplicationRecord
      belongs_to :conversation, touch: true
    end
    
    class Conversation < ApplicationRecord
      has_many :messages, -> { order(created_at: :desc) }
      belongs_to :sender, foreign_key: :sender_id, class_name: 'User'
      belongs_to :recipient, foreign_key: :recipient_id, class_name: 'User'
    end
    
    class User < ApplicationRecord
      has_many :conversations, -> (user) { unscope(where: :user_id).where('conversations.sender_id = ? OR conversations.recipient_id = ?', user.id, user.id) }
    end
    
    class ConversationsController < ApplicationController
      def index
        @user = User.find_by(email: params[:email])
    
        # "joins(:messages)" allows only retrieving conversations having at least one message, and does not include conversation with 0 message
        # now ordering by `updated_at: :asc` because `Message belongs_to :conversation, touch: true`, in which Conversation's updated_at will be automatically "touched"/updated whenever the associated Messages are updated/created.
        @conversations = @user.conversations.joins(:messages).order(updated_at: :asc).distinct
    
        json_response = @conversations.as_json(
          only: [:id, :updated_at],
          include: {
            sender: {
              only: [:id, :first_name, :last_name, :email]
            },
            recipient: {
              only: [:id, :first_name, :last_name, :email]
            },
            messages: {
              only: [:body, :created_at]
            }
          }
        )
    
        render json: json_response
      end
    end

    예제 요청

    Started GET "/conversations?email=foobar@example.com"

    예제 응답

    [{
      "id": 2,
      "updated_at": "2018-02-02T11:17:45.376Z",
      "sender": {
        "id": 4,
        "first_name": "Lorem",
        "last_name": "Ipsum",
        "email": "loremipsum@example.com"
      },
      "recipient": {
        "id": 1,
        "first_name": "Foo",
        "last_name": "Bar",
        "email": "foobar@example.com"
      },
      "messages": [{
        "body": "Hello there",
        "created_at": "2018-02-02T11:17:45.367Z"
      }, {
        "body": "Whatcha doin'?",
        "created_at": "2018-02-02T11:17:36.451Z"
      }, {
        "body": "hahaha :)",
        "created_at": "2018-02-02T11:03:29.843Z"
      }]
    }, {
      "id": 1,
      "updated_at": "2018-02-02T11:36:14.275Z",
      "sender": {
        "id": 1,
        "first_name": "Foo",
        "last_name": "Bar",
        "email": "foobar@example.com"
      },
      "recipient": {
        "id": 5,
        "first_name": "Ruby",
        "last_name": "Rails",
        "email": "rubyonrails@example.com"
      },
      "messages": [{
        "body": "hello Ruby-on-Rails! :)",
        "created_at": "2018-02-02T11:36:14.267Z"
      }]
    }]

    .as_json 여기

    touch : true사용 방법은 여기 에서 확인할 수 있습니다.

    작동 테스트



     

     

     

     

    출처 : https://stackoverflow.com/questions/48567068/looking-to-make-this-active-record-query-more-performant-ruby-on-rails

    댓글

Designed by Tistory.