2016-11-23 5 views
1

쿼리를 작성하고 사용자 정의 가중치 계산에 따라 정렬하려고합니다.장고 가중치 쿼리 (주석 값)

는 내가 실제로 작동 하는가에 와서 한 솔루션으로 어떤 도움을 필요로하지만 난 그게

내가 가지고있는 것은 미디어 객체입니다 싶습니다 곳 성능은 아니다. 관련 댓글, 좋아요 및 주문이 있습니다.

products = Media.objects \ 
     .select_related(
      'image', 
      'currency', 
      'user', 
      'user__image', 
     ) \ 
     .prefetch_related('category', 'tags') \ 
     .exclude(is_deleted=1) \ 
     .filter(Q(category__category__in=categories) | Q(tags__tag__title=query)) \ 
     .annotate(order_count = Count('orders', distinct=True)) \ 
     .annotate(comment_count = Count('comments', distinct=True)) \ 
     .annotate(like_count = Count('likes', distinct=True)) \ 
     .annotate(weight = Count(0)) \ 
     .distinct() 

    for m in products.iterator(): 
     initial_weight = int(m.order_count)*40 + int(m.comment_count)*4 + int(m.like_count)*4 + int(m.clicks) 
     m.weight  = float(float(initial_weight) - float(m.views/50)) 

당신은 내가 개별적으로 내가 사용하게 될 모든 매개 변수를 주석 한 후 산술의 전체 바보 반복을하고있는 중이 야 볼 수 있듯이 : 현재 작동하지만 완전한 해키 엉망 무엇

는 다음의 쿼리입니다 매우 하위 최적 인 queryset의 모든 항목에 대한 작업. - 장고 항상 주석 값이 서로 다른의했다 불평 주석의

products = Media.objects \ 
     .select_related(
      'image', 
      'currency', 
      'user', 
      'user__image', 
     ) \ 
     .prefetch_related('category', 'tags') \ 
     .exclude(is_deleted=1) \ 
     .filter(Q(category__category__in=categories) | Q(tags__tag__title=query)) \ 
     .annotate(weight = Count('orders', distinct=True) * 40 + Count('comments', distinct=True) * 4 + Count('likes', distinct=True) - F('views')/50 + F('clicks')) 

그러나 비슷한 작업 (와 합계()없이 몇 가지 변화를 시도 불가능했다 : 내가하고 시도 된

것은 다음이었다 입력합니다.

을 우리는이 프로젝트에 대해 장고 1.8을 사용하고 그런데. 내 원하는 정렬 가중치를 얻기에 좋은 단일 쿼리 aproach가

있습니까?

편집 :

내 최종 솔루션 (Назар 덕분에)

media_list = Media.objects \ 
     .select_related('user', 'user__image', 'image', 'currency') \ 
     .filter(user__in=suggested_users) \ 
     .filter(created_at__gt=seven_days_ago) \ 
     .exclude(sold=True) \ 
     .annotate(order_count = Count('orders', distinct=True)) \ 
     .annotate(comment_count = Count('comments', distinct=True)) \ 
     .annotate(like_count = Count('likes', distinct=True)) \ 
     .annotate(
      initial_weight=ExpressionWrapper((F('order_count') * 40 + F('comment_count') * 4 + \ 
          F('like_count') * 4 + F('clicks')), output_field=FloatField()) 
     ) \ 
     .annotate(
      views_divided=ExpressionWrapper(F('views')/Decimal(50.0), output_field=FloatField()) 
     ) \ 
     .annotate(weight=F('initial_weight') - F('views_divided')) \ 
     .distinct() 

답변

1

먼저, 해당 부문 (반올림하지 않고) 수레를 얻을 것이다 있는지 확인해야합니다.

products = Media.objects \ 
    .exclude(is_deleted=1) \ 
    .filter(Q(category__category__in=categories) | Q(tags__tag__title=query)) \ 
    .annotate(order_count = Count('orders', distinct=True)) \ 
    .annotate(comment_count = Count('comments', distinct=True)) \ 
    .annotate(like_count = Count('likes', distinct=True)) \ 
    .annotate(weight = Count(0)) \ 
    .annotate(
     initial_weight=ExpressionWrapper(
      F('order_count') * 40 + F('comment_count') * 4 + \ 
      F('like_count') * 4 + F('clicks'), 
      output_field=FloatField() 
     ) 
    ) \ 
    .annotate(
     views_divided=ExpressionWrapper((F('views')/Decimal(50.0), 
             output_field=FloatField())) 
    ) \ 
    .annotate(weight=F('initial_weight') - F('views_divided')) \ 
    .distinct() 

못생긴 외모,하지만 (내가 생각하는) 작동합니다 :

ExpressionWrapper(
    (F('views')/Decimal(50.0), 
    output_field=FloatField()), 
) 

따라서, 쿼리는 다음과 같이 보일 것이다 :이 (disgracefully stolen here) 같은 것을해야합니다. 만 weight을 계산해야하는 경우, 당신은 실제로 prefetch_relatedselect_realted를 사용하지 않아도, 장고는 그 물건 자체 (그러나, 그냥 내 추측이야 알아서합니다 - - 당신이 실제로 사람들을 사용하는 경우 보조 노트에

나중에 코드에서 외래 키를 누른 다음 정당화됩니다).

+0

정말 고마워요. 그래,보기 싫지만 ExpressionWrapper가 일을했다! 하나의 노트 (조금 이상한)가 initial_weight 및 ExpressionWrapper를 감싸는 데에만 필요합니다! 최종 해결책으로 편집하겠습니다. 추신 : 다른 목적으로 select_related가 필요하지만 필요하지 않다는 사실도 가치가 있습니다! 대단히 감사합니다. –

+0

도움이 되니 기쁩니다. 누군가가 귀하의 질문에 비틀 거릴 경우를 대비하여 답변을 업데이트 할 것입니다. –