мне приходят товары, много товаров, приходят товары в пакетах (не важно, сколько товаров хранит в себе пакет, если в пакете П1 товар А и Б, то в данный момент для товаров актуальный пакет П1)
Один и тот же товар может прийти ко мне сколько угодно раз
Тобишь, если он пришёл несколько раз, то и пакетов вскрытых (в нужном статусе)
у меня много (значит может товар А прийти в П2 и товар Б в П3 или они придут в пакете П4 все вместе), то если товар А пришел в П2, то последний пакет для товара А какой? Правильно, П2, значит запись, где товар А был в П1 мне уже не актуальна, если товар Б пришел в П3, то ласт пакет для товара Б какой? Правильно, П3, П2 мне уже не актуален по аналогии с другим вариантом, надеюсь ты понял🙏)
И вот мне надо сделать выборку всех товаров, у которых последний пакет находится в нужном мне статусе))
Products.objects.annotate( latest_package_in_needed_status=Subquery( Package.objects.filter(status=your_status, products=OuterRef('id')).order_by('-id').values_list('id', flat=True)[:1] ) ).filter( latest_package_in_needed_status__isnull=False ).values_list('latest_package_in_needed_status', flat=True)
оно получается возвращает по-очереди последний пакет с нужным статусом у меня есть два пакета с одним и тем же товаром А, П1 пришел раньше чем П2, значит П2 это последний пакет для товара А Оба пакета у меня лежат в нужном статусе и запрос возвращает последний пакет — П2 Но если я П2, последнему пакету, сделаю не нужный мне статус, то этот товар не должен попасть в кверисет, а он попадает, так как возвращает предыдущий (П1) пакет в нужном мне статусе, а надо бы в таком случае такой товар скипать и проверять следующий(
Ну тут надо тогда проверять еще есть ли пакет с этим товаром у которого айдишник больше чем у того что с нужным статусом
Оставь эту затею, тут что-то рекурсивное надо писать) на орм не получится
если результаты аннотаций можно сравнивать то получится
вопрос не чилтал, возможно вместо сабквери можено использовать префетч релейтид с объектом префетч, так можно префетчить больше одного значения и отфильтровать их
Product.objects.annotate( latest_package_in_needed_status_id=Subquery( Package.objects.filter(products=OuterRef('id'), status=your_status).order_by('-id').values_list('id', flat=True)[:1] ), latest_package_id=Subquery( Package.objects.filter(products=OuterRef('id')).order_by('-id').values_list('id', flat=True)[:1] ) ).filter( latest_package_in_needed_status_id__isnull=False, latest_package_id__isnull=False, latest_package_in_needed_status_id=F('latest_package_id') ).values_list('latest_package_in_needed_status_id', flat=True) выглядит конечно стремно но вот к чему я пришел
да, ща, после ормки))
Это трата времени на орм) и на попытку такое написать на sql
чем мой последний варик с орм неправильный?
Сек, гляну его с компа, а то с телефона код смотреть тяжело) только критиковать с него могу)
Пушка, это работает🙏🙏🙏
Бодя лучший! @bskqd лучший))
нашел решение оптимизированное Product.objects.annotate( latest_package_in_needed_status_id=Subquery( Package.objects.filter(products=OuterRef('id'), status=your_status).order_by('-id').values_list('id', flat=True)[:1] ), ).prefetch_related( Prefetch('packages', queryset=Package.objects.order_by('-id')[:1]), ).filter( packages__isnull=False, latest_package_in_needed_status_id__isnull=False, packages=F('latest_package_in_needed_status_id') ).values_list('latest_package_in_needed_status_id', flat=True)
оптимизация не робит)🙃
ага Cannot filter a query once a slice has been taken.
а, мне ж надо вернуть объекты продуктов, а в запросе твоем .values_list('latest_package_in_needed_status_id')
тут я валью лист делитнул и оно робит норм а тут с префетчем не дружит
Без вальюс листа не работает к сожалению да, жаль
вот только не мог понять, latest_package_in_needed_status_id и latest_package_id — это ж объекты пакетов а что значит latest_package_in_needed_status_id__isnull=False?
пытаюсь перевести на человеческий язык, и получается: аннотируем переменную для сбора нужного последнего пакета с нужным статусом по айди товара — latest_package_in_needed_status_id аннотируем переменную latest_package_id чтобы вогнать туда только ласт пакет (не смотря на статус) по айди товара а вот потом что в фильтрах происходит? и правильно ли я понял запрос?
Правильно а в фильтрах я смотрю что вообще есть пакеты с таким продуктом, что есть пакеты с таким продуктом и нужным статусом и потом сравниваю что последний пакет с нужным статусом это последний пакет для этого продукта
понял, спасибо тебе большое🙏
Обсуждают сегодня