Opened 3 years ago

Closed 3 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)

comment:1 by Mariusz Felisiak, 3 years ago

Cc: Mads Jensen added

I don't think there is a significant difference between them. ARRAY_AGG() returns array and JSONB_AGG() return JSON array, so when you aggregate JSONFields with JSONBAgg() then you can use key and index transforms which don't work with ArrayAgg() annotations.

comment:2 by Claude Paroz, 3 years ago

Then adding tests/docs with calling JSONBAgg on a JSONField would be great.

comment:3 by Mariusz Felisiak, 3 years ago

Triage Stage: UnreviewedAccepted

Agreed.

comment:4 by Abhyudai, 3 years ago

Owner: changed from nobody to Abhyudai
Status: newassigned

in reply to:  1 ; comment:5 by Abhyudai, 3 years ago

Replying to Mariusz Felisiak:

I don't think there is a significant difference between them. ARRAY_AGG() returns array and JSONB_AGG() return JSON array, so when you aggregate JSONFields with JSONBAgg() then you can use key and index transforms which don't work with ArrayAgg() 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.

in reply to:  5 comment:6 by Mariusz Felisiak, 3 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:9 by Abhyudai, 3 years ago

Thanks, Mariusz, for the explanation.

Last edited 3 years ago by Tim Graham (previous) (diff)

comment:10 by Abhyudai, 3 years ago

Has patch: set

comment:11 by Mariusz Felisiak, 3 years ago

Patch needs improvement: set

comment:12 by Abhyudai, 3 years ago

Patch needs improvement: unset

comment:13 by Mariusz Felisiak, 3 years ago

Patch needs improvement: set

comment:14 by Abhyudai, 3 years ago

Patch needs improvement: unset

comment:15 by Mariusz Felisiak, 3 years ago

Triage Stage: AcceptedReady for checkin

comment:16 by Mariusz Felisiak <felisiak.mariusz@…>, 3 years ago

Resolution: fixed
Status: assignedclosed

In 5a634a7b:

Fixed #32906 -- Added docs and tests for using key and index lookups on JSONBAgg results.

Co-authored-by: Mariusz Felisiak <felisiak.mariusz@…>

Note: See TracTickets for help on using tickets.
Back to Top