Django annotate count in JSONField with Postgres

浪子不回头ぞ 提交于 2019-12-01 09:26:33

You can use jsonb_extract_path_text via a Func object as an alternative to the field transform:

Pet.annotate(dinner=Func(
    F('data'), Value('diet'), Value('dinner'),
    function='jsonb_extract_path_text'))  \
.values('dinner')  \
.annotate(total=Count('dinner'))

The reason why the field transform data__diet__dinner fails is an error within Django when you go deeper than just one level into the json structure and use GROUP BY in the SQL. The first level (name, animal, diet) should work fine.

The reason seems to be that for nested transforms, Django changes the SQL syntax used, switching from a single value to a list to specify the path into the json structure.

This is the syntax used for non-nested json transforms (= first level):

"appname_pet"."data" -> 'diet'

And this is the syntax used for nested transforms (deeper than first level):

"appname_pet"."data" #> ARRAY['diet', 'dinner']

While constructing the query, Django chokes on that list while working out the required GROUP BY clauses. This does not seem to be an inevitable restriction; the support for transforms is quite new, and this is possibly one of the kinks that haven't been worked out yet. So if you open a Django ticket, this might just work a few versions down the line.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!