Как использовать Django ORM для поиска висячих записей?
Как можно использовать Django ORM для написания чего-то похожего на следующий SQL:
SELECT * FROM entities
WHERE NOT EXISTS (SELECT 1 FROM apples WHERE apples.entity_id = entities.id)
AND NOT EXISTS (SELECT 1 FROM oranges WHERE oranges.entity_id = entities.id)
AND NOT EXISTS (SELECT 1 FROM bananas WHERE bananas.entity_id = entities.id)
У меня есть несколько мета-таблиц, которые ссылаются на фактическую запись с деталями, но возможно, что у этих записей нет ссылок, и в этом случае они "болтаются".
Проблема в том, что имеется более 100 миллионов записей, поэтому простой exclude с использованием in фильтра не работает:
Entity.objects.exclude(userid__in=Apple.objects.all().values_list('entity_id'))
SQL-оператор с использованием NOT EXISTS, с другой стороны, выполняется молниеносно.
В настоящее время я работаю на Django 2.2 (с планами обновления до 4.x в течение года).
Вы можете .filter(…) [Django-doc] с:
Entity.objects.filter(apple=None, orange=None, bana=None)
Это сделает LEFT OUTER JOIN на таблицах для моделей Apple, Orange и Banana, а затем проверит, являются ли они None/NULL.
It will work with the value related_query_name=… parameter [Django-doc] for the ForeignKeys from Apple, Orange and Banana to Entity. If that one is not specified, it will use the related_name=… parameter [Django-doc] instead, and if that is not specified either, it uses the name of the model in lowercase, so here apple, orange and banana.