2

의 당신이이처럼 모델 중 하나에 assocation 있다고 가정 해 봅시다 :효율적인 액티브 협회 조건

class User 
    has_many :articles 
end 

지금 당신이 어제 쓴 기사 중 하나를 3 개 배열, 쓴 기사 하나를 얻을 필요가 가정 지난 7 일간, 그리고 지난 30 일 동안 작성된 기사 중 하나입니다.

물론 당신은이 작업을 수행 할 수 있습니다

articles_yesterday = user.articles.where("posted_at >= ?", Date.yesterday) 
articles_last7d = user.articles.where("posted_at >= ?", 7.days.ago.to_date) 
articles_last30d = user.articles.where("posted_at >= ?", 30.days.ago.to_date) 

그러나,이 3 개 별도의 데이터베이스 쿼리를 실행합니다. 더 효율적으로, 당신이 할 수 있습니다 :

articles_last30d = user.articles.where("posted_at >= ?", 30.days.ago.to_date) 
articles_yesterday = articles_last30d.select { |article| 
    article.posted_at >= Date.yesterday 
} 
articles_last7d = articles_last30d.select { |article| 
    article.posted_at >= 7.days.ago.to_date 
} 

지금 물론 이것은 인위적인 예입니다 및 배열이 실제로 데이터베이스 쿼리보다 더 빨리 될 것입니다 선택할 수 있지만 그냥 그것으로 가정 않는다는 보장은 없습니다.

내 질문에 : 당신이 단순히 연결 조건을 지정하여이 문제를 제거하는 방식으로이 코드를 작성하는 방법 (예 : 일부 보석)이 있으며 응용 프로그램 자체가 수행해야하는지 여부를 결정합니다 다른 데이터베이스 쿼리 또는하지?

ActiveRecord 자체가이 문제를 적절하게 다루지 않는 것 같습니다. 매번 데이터베이스를 쿼리하거나 연관을 배열로 처리해야합니다.

당신은 협회의 정의에 조건 해시를 지정하여 원하는 각 수준에 대해 별도의 연결을 만들 수 있습니다

+0

무엇을 없애시겠습니까? 추가 배열, 추가 쿼리 또는 타이핑? – Matzi

+0

내 실제 코드에서는 어떤 연관성이 이미로드되었는지 여부를 알지 못합니다. 나는 이것을 신경 쓸 필요가없는 코드를 작성하고, 여전히 최소한의 데이터베이스 쿼리를 작성하고 싶다. –

+0

나는 이것을위한 박스 솔루션이 없다고 생각합니다. 모든 조건과로드 된 데이터를 추적하려면 많은 노력이 필요합니다.데이터베이스가 장면 뒤에서 바뀔 수 있다는 사실에 대해서 이야기하지 않아도됩니다. 최적의 쿼리를 수동으로 만들어야합니다. 이를 위해 트릭을 사용하여 간단하게 만들 수 있습니다. – Matzi

답변

0

이 처리 할 수있는 몇 가지 방법이 있습니다. 그런 다음 사용자 쿼리에 대해 이러한 연결을 간단하게로드 할 수 있으며 각 사용자에 대해 3x가 아닌 전체 작업에 대해 db 3x를 사용하게됩니다.

class User 
    has_many articles_yesterday, class_name: Article, conditions: ['posted_at >= ?', Date.yesterday] 
    # other associations the same way 
end 

User.where(...).includes(:articles_yesterday, :articles_7days, :articles_30days) 

으로 그룹을 만들 수 있습니다. 이 내려 온다 무엇

+0

불행히도 이것으로는 충분하지 않습니다. 가능한 한로드하는 것이 좋습니다.이 시나리오에서는 성능에 중요한 응용 프로그램이기 때문에 세 개가 아닌 하나의 연결 만 열정적으로로드해야합니다. –

0

당신은의 필요성을 제거 할 수 코드를 프로파일 링하고 (당신도 전혀 귀찮게해야하는 경우 또는) 앱 빠른 될 것 결정해야 할 것입니다 아래 코드와 같이 쿼리를 확인하십시오.

class User 
    has_many :articles 

    def article_30d 
    @articles_last30d ||= user.articles.where("posted_at >= ?", 30.days.ago.to_date) 
    end 

    def articles_last7d 
    @articles_last7d ||= articles_last30d.select { |article| article.posted_at >= 7.days.ago.to_date } 
    end 

    def articles_yesterday 
    @articles_yesterday ||= articles_last30d.select { |article| article.posted_at >= Date.yesterday } 
    end 

end 

그것은 무엇을 : 세 가지 중 하나가 사용되는 경우

  • 만 사용되는 배열을 계산하고, 어떤 경우에 30D 버전,하지만 한 번만, 단 하나 개의 쿼리 최대를 만든다

그러나 사용하지 않아도 초기 30d 쿼리가 단순화되지는 않습니다. 충분하니, 아니면 더 필요한 것이 있습니까?

+0

이것은 실제로 내가 지금하고있는 일입니다. 위의 예는 단순화입니다. –

관련 문제