Queryset for ancestors - Remove Extraneous Queries
Opened this issue · 0 comments
cancan101 commented
This issue can be summarized as having some way of getting a queryset
of a Node's ancestors without having to perform a query.
Using these Models:
class Category2(CTENode):
name = models.CharField(max_length = 128, null = False)
class Device(models.Model):
category = models.ForeignKey(Category2)
and running Device.objects.filter(category__in=Category2.objects.get(name="bottom").ancestors())
, I get two queries rather than one:
WITH RECURSIVE cte ("depth", "path", "ordering", "id") AS (
SELECT 1 AS depth,
array[T."id"] AS path,
array[T."id"] AS ordering,
T."id"
FROM app_category2 T
WHERE T."parent_id" IS NULL
UNION ALL
SELECT cte.depth + 1 AS depth,
cte.path || T."id",
cte.ordering || array[T."id"],
T."id"
FROM app_category2 T
JOIN cte ON T."parent_id" = cte."id")
SELECT (cte.ordering) AS "ordering", (cte.path) AS "path", (cte.depth) AS "depth", "app_category2"."id", "app_category2"."parent_id", "app_category2"."name" FROM "app_category2" , "cte" WHERE ((cte."id" = app_category2."id") AND "app_category2"."name" = 'bottom' );
SELECT "app_device"."id", "app_device"."category_id" FROM "app_device" WHERE "app_device"."category_id" IN (WITH RECURSIVE cte ("depth", "path", "ordering", "id") AS (
SELECT 1 AS depth,
array[T."id"] AS path,
array[T."id"] AS ordering,
T."id"
FROM app_category2 T
WHERE T."parent_id" IS NULL
UNION ALL
SELECT cte.depth + 1 AS depth,
cte.path || T."id",
cte.ordering || array[T."id"],
T."id"
FROM app_category2 T
JOIN cte ON T."parent_id" = cte."id")
SELECT "app_category2"."id" FROM "app_category2" , "cte" WHERE ((cte."id" = app_category2."id") AND "app_category2"."id" IN (2, 3))) LIMIT 21;
I think this is due in part to #3 because Category2.objects.get(name="bottom").ancestors()
runs a SQL query rather than just returning a queryset
. Is there another way to just get a queryset for the ancestors
?
One idea is to use something like this which is a queryset:
Category2.objects.get(name="bottom").values_list('path', flat=True)
but that does not work quite right since I have a queryset
of lists.