Лучше Alternate вместо использования цепных запросов на объединение в Django ORM - PullRequest
0 голосов
/ 13 октября 2018

Мне нужно было добиться чего-то подобного в Django ORM:

(SELECT * FROM `stats` WHERE MODE = 1 ORDER BY DATE DESC LIMIT 2) 
UNION
(SELECT * FROM `stats` WHERE MODE = 2 ORDER BY DATE DESC LIMIT 2)     
UNION                                                                       
(SELECT * FROM `stats` WHERE MODE = 3 ORDER BY DATE DESC LIMIT 2)
UNION                                                                         
(SELECT * FROM `stats` WHERE MODE = 6 ORDER BY DATE DESC LIMIT 2) 
UNION
(SELECT * FROM `stats` WHERE MODE = 5 AND is_completed != 3 ORDER BY DATE DESC)                                                                           
# mode 5 can return more than 100 records so NO LIMIT here 

, для которого я написал это:

query_run_now_job_ids = Stats.objects.filter(mode=5).exclude(is_completed=3).order_by('-date')
list_of_active_job_ids = Stats.objects.filter(mode=1).order_by('-date')[:2].union(
                            Stats.objects.filter(mode=2).order_by('-date')[:2],
                            Stats.objects.filter(mode=3).order_by('-date')[:2],
                            Stats.objects.filter(mode=6).order_by('-date')[:2],
                            query_run_now_job_ids)

, но каким-то образом list_of_active_job_ids возвращено неупорядоченнымто есть list_of_active_job_ids.ordered возвращает False , из-за чего, когда этот запрос передается классу Paginator , он дает:

UnorderedObjectListWarning: 
Pagination may yield inconsistent results with an unordered object_list  

Я уже установил порядок в классе Meta вmodels.py

class Meta:
        ordering = ['-date']

Без запроса paginator нормально работает и загружается страница, но с использованием paginator, представление никогда не загружается, оно продолжает загружаться.

Есть ли лучший альтернативный вариант для достижения этой цели без использования цепочкиunion.

Итак, я попробовал другую альтернативу для вышеупомянутого запроса MySQL, но я застрял в другой проблеме, чтобы записать условие для mode = 5 в этом запросе:

SELECT  
    MODE ,
    SUBSTRING_INDEX(GROUP_CONCAT( `job_id` SEPARATOR ',' ),',',2) AS job_id_list,
    SUBSTRING_INDEX(GROUP_CONCAT( `total_calculations` SEPARATOR ',' ),',',2) AS total_calculations
FROM `stats`            
ORDER BY DATE DESC 

Даже если бы мне удалось написать этот запрос, это привело бы меня к другой сложной ситуации, то есть к конвертации этого запроса для Django ORM.

Так почему My Query не упорядочен, даже если я установил его в Meta класса.

Также, если не этот запрос, есть ли лучший альтернативный вариант для достижения этого?

Помощь будет оценена!.

Я использую Python 2.7 и Django 1.11.

1 Ответ

0 голосов
/ 14 октября 2018

Хотя подзапросы могут быть упорядочены, итоговые данные объединения не являются.Вам нужно явно определить порядок.

from django.db import models

def make_query(mode, index):
    return (
        Stats.objects.filter(mode=mode).
        annotate(_sort=models.Value(index, models.IntegerField())).
        order_by('-date')
    )

list_of_active_job_ids = make_query(1, 1)[:2].union(
     make_query(2, 2)[:2],
     make_query(3, 3)[:2],
     make_query(6, 4)[:2],
     make_query(5, 5).exclude(is_completed=3)
).order_by('_sort', '-date')

Все, что я сделал, это добавил новое поле буквального значения _sort, которое имеет различное значение для каждого подзапроса, а затем упорядочено им в конечном запросе.Остальной код просто для уменьшения дублирования.Это было бы даже чище, если бы не этот mode=6 подзапрос.

...