Аннотируйте количество моделей по геометрическому пересечению

Проблема

Предполагая эти модели:

class ModelA(models.Model):
    geometry = models.PolygonField()

class ModelB(models.Model):
    geometry = models.PolygonField()

Как аннотировать к набору запросов ModelA подсчет пересекающихся экземпляров ModelB, используя только ORM? Геометрия каждого ModelA должна пересекаться с геометрией ModelB экземпляров, а пересекающиеся ModelB экземпляры подсчитываться.

В конечном итоге я хотел бы order_by подсчитать количество ModelB экземпляров и найти ModelA экземпляры, которые имеют наибольшее количество пересекающихся ModelB экземпляров.

Что я пробовал

ModelA.objects.annotate(
    n_modelb=Count(
        ModelB.objects.filter(geometry__intersects=OuterRef("geometry"))
    ),
)

--> ProgrammingError: subquery must return only one column


ModelA.objects.annotate(
    n_modelbSubquery(
        ModelB.objects.filter(geometry__intersects=OuterRef("geometry")).count()
    ),
)

--> ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.


ModelA.objects.annotate(
    modelb_ids=Subquery(
        ModelB.objects.filter(geometry__intersects=OuterRef("geometry")).values(
            "id"
        ),
    ),
    n_modelb=Count("modelb_ids"),
)

--> CardinalityViolation: more than one row returned by a subquery used as an expression


Связанные вопросы

Я думаю, что в основном я застрял на этом комментарии к этому ответу: https://stackoverflow.com/a/46154553/9778755.

Это решение работает, когда между моделями есть связь. Если вы пытаетесь считать по моделям без отношений, это не работает. - Danielle MadeleyMar 17 '20 at 6:36

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