Du kan använda jsonb_extract_path_text via en Func objekt som ett alternativ till fälttransformen:
Pet.annotate(dinner=Func(
F('data'), Value('diet'), Value('dinner'),
function='jsonb_extract_path_text')) \
.values('dinner') \
.annotate(total=Count('dinner'))
Anledningen till att fältet transformerar data__diet__dinner
fails är ett fel inom Django när du går djupare än bara en nivå in i json-strukturen och använd GROUP BY
i SQL. Den första nivån (name
, animal
, diet
) borde fungera bra.
Anledningen verkar vara att för kapslade transformationer ändrar Django SQL-syntaxen som används, och byter från ett enstaka värde till en lista för att ange sökvägen till json-strukturen.
Det här är syntaxen som används för icke-kapslade json-transformationer (=första nivån):
"appname_pet"."data" -> 'diet'
Och det här är syntaxen som används för kapslade transformationer (djupare än första nivån):
"appname_pet"."data" #> ARRAY['diet', 'dinner']
När Django konstruerar frågan kväver Django den listan medan han utarbetar den nödvändiga GROUP BY
klausuler. Detta verkar inte vara en oundviklig begränsning; stödet för transformeringar är ganska nytt, och det här är möjligen en av de kinks som inte har lösts ännu. Så om du öppnar en Django-biljett
, detta kanske bara fungerar några versioner längre fram.