2014-07-11 2 views
14

prefetch_related에게 관련 객체의 제한된 세트만을 가져 오는 방법이 있습니까? 사용자 목록을 가져 왔으며 최근 댓글을 가져오고 싶습니다. 루프의 각 사용자에 대한 주석을 가져 오는 대신 prefetch_related를 사용하여 사용자를 가져올 때 미리 가져옵니다. 필자는 원래 쿼리 결과에있는 모든 사용자가 작성한 모든 주석을 가져 오지만 각 사용자에 대해 최신 5 개만 보여주기를 원합니다.Django prefetch_related with limits

댓글 목록이 정말 큰 경우 어떻게 실적에 영향을 줍니까? 단일 (또는 2) 쿼리에서 각 사용자에 대해 5 개의 주석 만 가져 오는 방법이 있습니까? 그것은 사용자를 가져 오기위한 원래 쿼리와 동일한 쿼리 일 필요는 없지만 좋을 것입니다.

나는 기본적으로 사용자가 100 단위 또는 코멘트 젯 10000s가있는 경우 그래서, 그들은 모두 메모리에로드되지 않습니다이

User.objects.all().prefetch_related('comments', limit=10) 

처럼 무언가로이

users = User.objects.all() 
    for user in users: 
     user.comments.all()[:10] 

를 켜려고합니다. 어떻게 당신은 원시 SQL에서 이와 같은 것을 할 것입니까?

+0

프리 페치를 사용하는 것이 좋은 방법이라고 생각하지 않습니다. 실제로 prefetch_related는 각 관계에 대해 별도의 조회를 수행하고 Python으로 결합합니다. 즉, 파이썬에서 주석을 미리로드하고이 미리로드 된 주석 목록에서 조인을 수행한다는 의미입니다. 귀하의 경우, 각 사용자의 마지막 10 개의 주석을 가지고 모두를 미리로드해야합니다. – trnsnt

+0

관계 당 하나의 쿼리 만 사용할 수 있지만 개체 당 하나의 쿼리가 진정한 킬러입니다. –

+0

개체 당 하나의 쿼리가 악몽이라고 나는 동의합니다. 'users = User.objects.all(). prefetch_related ('comments')'이 경우 2 개의 쿼리 만 수행합니다. – trnsnt

답변

4

프리 페치 관련 객체의 수를 제한하는 유일한 방법은 Prefetch()를 사용하고 fileds를 필터링하는 것입니다. 즉 케이 동안 sliceing

User.objects.all().prefetch_related(
    Prefetch('msg_sent', queryset=UserMsg.objects.order_by('-created')[:10])) 

사용

from datetime import datetime, timedelta 
timelimit = datetime.now() - timedelta(days=365) 

User.objects.all().prefetch_related(
    Prefetch('msg_sent', queryset=UserMsg.objects.filter(created__gte=timelimit))) 

예컨대 에러

AssertionError: Cannot filter a query once a slice has been taken. 

에게 관련 개체들의 수가 값 필터를 사용하는 것 제한하는 유일한 방법을 반환 고정 된 숫자를 반환하는 것은 어떤 상황에서는 유용 할 수 있으며, 프리 페치 된 객체의 수를 줄입니다.

+7

다음은'Prefetch' 객체가 조각이있는 쿼리 세트를 받아들이지 않는 것에 대한 티켓입니다 : https : //code.djangoproject. co.kr/ticket/26780 –