Как использовать 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.

Вернуться на верх