Opened 4 years ago
Closed 4 years ago
#32906 closed Cleanup/optimization (fixed)
Explain JSONBAgg benefit
| Reported by: | Claude Paroz | Owned by: | Abhyudai |
|---|---|---|---|
| Component: | Documentation | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Mads Jensen | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
When reading current Django docs and tests, I can't see how JSONBAgg has any advantage over ArrayAgg. It would be great to add both in docs and tests examples showing benefits/differences between ArrayAgg and JSONBAgg, if any.
Change History (14)
follow-up: 5 comment:1 by , 4 years ago
| Cc: | added |
|---|
comment:2 by , 4 years ago
Then adding tests/docs with calling JSONBAgg on a JSONField would be great.
comment:4 by , 4 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
follow-up: 6 comment:5 by , 4 years ago
Replying to Mariusz Felisiak:
I don't think there is a significant difference between them.
ARRAY_AGG()returns array andJSONB_AGG()return JSON array, so when you aggregateJSONFields withJSONBAgg()then you can use key and index transforms which don't work withArrayAgg()annotations.
As far I can see, they both are giving the same results.
# model class AggregateTestModel(PostgreSQLModel): """ To test postgres-specific general aggregation functions """ json_field = models.JSONField(null=True)
# shell >>> AggreTestModel.objects.bulk_create( AggregateTestModel(json_field={'lang': 'pl'}), AggregateTestModel(json_field={'lang': 'en'}), AggregateTestModel(json_field={'breed': 'collie'}) ) >>> AggregateTestModel.objects.all().values_list('json_field', flat=True) <QuerySet [None, {'lang': 'pl'}, {'lang': 'en'}, {'breed': 'collie'}]> >>> AggregateTestModel.objects.aggregate(val=JSONBAgg('json_field')) {'val': [None, {'lang': 'pl'}, {'lang': 'en'}, {'breed': 'collie'}]} >>> jsonb = AggregateTestModel.objects.aggregate(val=JSONBAgg('json_field')) >>> jsonb {'val': [None, {'lang': 'pl'}, {'lang': 'en'}, {'breed': 'collie'}]} >>> arr = AggregateTestModel.objects.aggregate(val=ArrayAgg('json_field')) >>> arr {'val': [None, {'lang': 'pl'}, {'lang': 'en'}, {'breed': 'collie'}]} >>> arr == jsonb True >>> type(arr) <class 'dict'> >>> type(jsonb) <class 'dict'>
Am I missing something here? The above snippet is just an abstracted version of the model inside the package postgres_tests.models, used for tests.
comment:6 by , 4 years ago
Replying to Abhyudai:
Am I missing something here? The above snippet is just an abstracted version of the model inside the package
postgres_tests.models, used for tests.
They are not the same on the PostgreSQL-level because ARRAY_AGG() returns array and JSONB_AGG() returns JSON array, see my comment. For example:
>>> AggregateTestModel.objects.annotate(jsonbagg=JSONBAgg('json_field')).filter(jsonbagg__0__lang='en').values('jsonbagg')
<QuerySet [{'jsonbagg': [{'lang': 'en'}]}]>
>>> AggregateTestModel.objects.annotate(arrayagg=ArrayAgg('json_field')).filter(arrayagg__0__lang='en').values('arrayagg')
File "/django/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.SyntaxError: syntax error at or near "["
LINE 1: ..."postgres_tests_aggregatetestmodel"."json_field" )[1] -> 'la...
comment:11 by , 4 years ago
| Patch needs improvement: | set |
|---|
comment:12 by , 4 years ago
| Patch needs improvement: | unset |
|---|
comment:13 by , 4 years ago
| Patch needs improvement: | set |
|---|
comment:14 by , 4 years ago
| Patch needs improvement: | unset |
|---|
comment:15 by , 4 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
I don't think there is a significant difference between them.
ARRAY_AGG()returns array andJSONB_AGG()return JSON array, so when you aggregateJSONFields withJSONBAgg()then you can use key and index transforms which don't work withArrayAgg()annotations.