Уведомления

Группа в Telegram: @pythonsu

#1 Май 13, 2014 12:05:53

chaotism
От:
Зарегистрирован: 2010-11-29
Сообщения: 76
Репутация: +  1  -
Профиль   Отправить e-mail  

Альтернатива distinct()

У distinct() есть несколько неудобвств в текущее время:
а) не работает с mysql
б) не работает с агрегатными функциями, тот же count не посчитать

Вопрос знатокам:
как удалить повторы в query sets:?

    
    queryset = Source.objects.all().filter(pk__in=my_filter(queryset))
    def my_filter(self,queryset):
        old_pk = queryset[0].pk
        new_queryset = queryset.none()
        for f in queryset.order_by('pk'):
            if f.pk == old_pk:
                continue
            old_pk = f.pk
            yield f.pk
в целом работало пока количество записей было в пределах 10000, подцепил базу с 10000000 и подавился.
из более правильного варианта фильтрации что посоветуете? через индексы делать срезы и потом queryset склеивать через | и & ?



Отредактировано chaotism (Май 13, 2014 12:06:27)

Офлайн

#2 Май 13, 2014 12:46:36

GreyZmeem
От: Киев
Зарегистрирован: 2013-12-03
Сообщения: 147
Репутация: +  34  -
Профиль   Отправить e-mail  

Альтернатива distinct()

Опишите словами какую выборку вы хотите сделать, а то из кода не совсем понятно
PK и так должен быть уникальным, как он может повторяться?

Офлайн

#3 Май 13, 2014 14:21:46

chaotism
От:
Зарегистрирован: 2010-11-29
Сообщения: 76
Репутация: +  1  -
Профиль   Отправить e-mail  

Альтернатива distinct()

Есть вьюха на rest framework, в filter_queryset фильтруется базовый запрос в зависимости от пользователя или даты.
Не понимаю почему, но бывает если фильтруешь по пользователю вылезают дублирующиеся ресурсы. Если со временем в принципе понятно откуда они, то по пользователям грешу на внешние ключи. При использовании distinct() лишнее я фильтровал в return queryset.distinct('pk') в конце функции. Сейчас другой программист в serealizer е добавил расчет опирающийся на queryset.count() и return queryset.distinct('pk') валиться с ошибкой. Вот хотел узнать как лучше ручками изобразить действие distinct над кверисетом, без возможности делать длинные списки и множества

class SourcePaginatedAPIView(generics.ListAPIView):
    queryset = Source.objects.all().prefetch_related()
    serializer_class = SourceSerializer
    pagination_serializer_class = SizeSourcePaginatedSerializer
    paginate_by = 10
    paginate_by_param = 'page_size'
    max_paginate_by = 100
    def get(self, request, *args, **kwargs):
        self.paginate_by = self.kwargs.get('paginate_count', None)
        return self.list(request, *args, **kwargs)
    def filter_queryset(self, queryset):
        filters = self.request.GET.get('filter', '')
        datesCreateTask = filters.get('datesCreate', {})
        users = filters.get('users', {})
		if datesCreateTask:
			data_query = Source.objects.none()
			for date in datesCreateTask:
				start_date = datetime.strptime(date['value1']+'.23:59', '%d.%m.%Y.%H:%M')
				stop_date = datetime.strptime(date['value2']+'.23:59', '%d.%m.%Y.%H:%M')
				data_query = data_query|Source.objects.filter(Q(sourceprocessing__task__create_time__gte=start_date) & Q(sourceprocessing__task__create_time__lte=stop_date))
			queryset = queryset&data_query
		if users:
			# task = Task.objects.filter(user__username__in=[user['value'] for user in users])
			# subtask = Subtask.objects.filter(task__in=task)
			# user_query = Source.objects.filter(Q(subtask__in=subtask))
			queryset = queryset.filter(Q(sourceprocessing__task__user__pk__in=(user['value'] for user in users)))
		return queryset



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version