У меня есть модель "myModel", сохраняющая некоторые данные в (postgresql) jsonField с именем "json". Типичная структура данных json: {key: [{"a": 1, "b": 2}, {"a": 3, "b": 4}]}.
Я бы хотел отфильтровать набор запросов myModel по значениям "a" или "b".Я могу также захотеть агрегировать по «a» или «b»
Так что «unnesting» массив (json -> key) будет очень полезен, но я не могу понять, как это сделать с помощью djangoapi.
Я попытался выполнить "unnesting" прямо в postgresql с помощью следующего SQL-запроса.
SELECT *
FROM "myModel"
join lateral jsonb_to_recordset("myModel"."json" -> 'key') as r("a" int, "b" int) on true
LIMIT 5
Мы можем даже сделать его более компактным, используя сокращенную запись для бокового соединения
SELECT *
FROM "myModel", jsonb_to_recordset("myModel"."json" -> 'key') as r("a" int, "b" int)
LIMIT 5
Но я понятия не имею, как сделать что-то эквивалентное с помощью API django.Я пробовал несколько вещей с аннотацией и RawSQL, но ни одна из них, похоже, не действует в предложении «FROM».Именно в это место я должен добавить оператор 'jsonb_to_recordset'.Возможно, я мог бы использовать функцию raw для размещения моего исходного SQL, но это означало бы, что я не могу «фильтровать» или «агрегировать» объединенный набор запросов с помощью API django…. Мне нужно делать все в rawSQL.что не очень удобно для того, что я должен сделать.
Другой подход - использовать функцию «extra» queryset, которая позволяет добавить дополнительную таблицу в предложении sql FROM.К сожалению, если я сделаю:
qs = myModel.objects.all()
qs = qs.extra(tables = ["""jsonb_to_recordset("myApp_myModel"."json" -> 'key') as r("a" int, "b" int)"""])
qs = qs.values()
print(qs.query)
я получу запрос, который django выполнит:
SELECT *
FROM "myModel", "jsonb_to_recordset("myModel"."json" -> 'key') as r("a" int, "b" int)"
Это довольно близко к тому, что мне нужно ... за исключением того, что django добавил дополнительные кавычки вокругдополнительное имя «таблицы», которое я предоставил ... Так что функция больше не работает.
Есть идеи, как с этим справиться?
Заранее спасибо, Loic