Browse Source

Fixed #32169 -- Added distinct support to JSONBAgg.

Artur Beltsov 4 years ago
parent
commit
18c8ced81e

+ 2 - 1
django/contrib/postgres/aggregates/general.py

@@ -43,7 +43,8 @@ class BoolOr(Aggregate):
 
 class JSONBAgg(OrderableAggMixin, Aggregate):
     function = 'JSONB_AGG'
-    template = '%(function)s(%(expressions)s %(ordering)s)'
+    template = '%(function)s(%(distinct)s%(expressions)s %(ordering)s)'
+    allow_distinct = True
     output_field = JSONField()
 
     def convert_value(self, value, expression, connection):

+ 8 - 1
docs/ref/contrib/postgres/aggregates.txt

@@ -114,10 +114,17 @@ General-purpose aggregation functions
 ``JSONBAgg``
 ------------
 
-.. class:: JSONBAgg(expressions, filter=None, ordering=(), **extra)
+.. class:: JSONBAgg(expressions, distinct=False, filter=None, ordering=(), **extra)
 
     Returns the input values as a ``JSON`` array.
 
+    .. attribute:: distinct
+
+        .. versionadded:: 3.2
+
+        An optional boolean argument that determines if array values will be
+        distinct. Defaults to ``False``.
+
     .. attribute:: ordering
 
         .. versionadded:: 3.2

+ 3 - 0
docs/releases/3.2.txt

@@ -131,6 +131,9 @@ Minor features
 * The new :attr:`.JSONBAgg.ordering` attribute determines the ordering of the
   aggregated elements.
 
+* The new :attr:`.JSONBAgg.distinct` attribute determines if aggregated values
+  will be distinct.
+
 * The :class:`~django.contrib.postgres.operations.CreateExtension` operation
   now checks that the extension already exists in the database and skips the
   migration if so.

+ 12 - 0
tests/postgres_tests/test_aggregates.py

@@ -428,6 +428,18 @@ class TestAggregateDistinct(PostgreSQLTestCase):
         values = AggregateTestModel.objects.aggregate(arrayagg=ArrayAgg('char_field', distinct=True))
         self.assertEqual(sorted(values['arrayagg']), ['Bar', 'Foo'])
 
+    def test_json_agg_distinct_false(self):
+        values = AggregateTestModel.objects.aggregate(
+            jsonagg=JSONBAgg('char_field', distinct=False),
+        )
+        self.assertEqual(sorted(values['jsonagg']), ['Bar', 'Foo', 'Foo'])
+
+    def test_json_agg_distinct_true(self):
+        values = AggregateTestModel.objects.aggregate(
+            jsonagg=JSONBAgg('char_field', distinct=True),
+        )
+        self.assertEqual(sorted(values['jsonagg']), ['Bar', 'Foo'])
+
 
 class TestStatisticsAggregate(PostgreSQLTestCase):
     @classmethod