Quellcode durchsuchen

Support InfluxDB count distinct aggregation (#11658)

influxdb: support count distinct aggregation
Kim Christensen vor 7 Jahren
Ursprung
Commit
48fc5edda1

+ 8 - 0
pkg/tsdb/influxdb/query_part_test.go

@@ -76,5 +76,13 @@ func TestInfluxdbQueryPart(t *testing.T) {
 			res := part.Render(query, queryContext, "mean(value)")
 			res := part.Render(query, queryContext, "mean(value)")
 			So(res, ShouldEqual, `mean(value) AS "test"`)
 			So(res, ShouldEqual, `mean(value) AS "test"`)
 		})
 		})
+
+		Convey("render count distinct", func() {
+			part, err := NewQueryPart("count", []string{})
+			So(err, ShouldBeNil)
+
+			res := part.Render(query, queryContext, "distinct(value)")
+			So(res, ShouldEqual, `count(distinct(value))`)
+		})
 	})
 	})
 }
 }

+ 23 - 0
public/app/plugins/datasource/influxdb/query_part.ts

@@ -44,6 +44,28 @@ function replaceAggregationAddStrategy(selectParts, partModel) {
   for (var i = 0; i < selectParts.length; i++) {
   for (var i = 0; i < selectParts.length; i++) {
     var part = selectParts[i];
     var part = selectParts[i];
     if (part.def.category === categories.Aggregations) {
     if (part.def.category === categories.Aggregations) {
+      if (part.def.type === partModel.def.type) {
+        return;
+      }
+      // count distinct is allowed
+      if (part.def.type === 'count' && partModel.def.type === 'distinct') {
+        break;
+      }
+      // remove next aggregation if distinct was replaced
+      if (part.def.type === 'distinct') {
+        var morePartsAvailable = selectParts.length >= i + 2;
+        if (partModel.def.type !== 'count' && morePartsAvailable) {
+          var nextPart = selectParts[i + 1];
+          if (nextPart.def.category === categories.Aggregations) {
+            selectParts.splice(i + 1, 1);
+          }
+        } else if (partModel.def.type === 'count') {
+          if (!morePartsAvailable || selectParts[i + 1].def.type !== 'count') {
+            selectParts.splice(i + 1, 0, partModel);
+          }
+          return;
+        }
+      }
       selectParts[i] = partModel;
       selectParts[i] = partModel;
       return;
       return;
     }
     }
@@ -434,4 +456,5 @@ export default {
   getCategories: function() {
   getCategories: function() {
     return categories;
     return categories;
   },
   },
+  replaceAggregationAdd: replaceAggregationAddStrategy,
 };
 };

+ 144 - 0
public/app/plugins/datasource/influxdb/specs/query_part.jest.ts

@@ -40,5 +40,149 @@ describe('InfluxQueryPart', () => {
       expect(part.text).toBe('alias(test)');
       expect(part.text).toBe('alias(test)');
       expect(part.render('mean(value)')).toBe('mean(value) AS "test"');
       expect(part.render('mean(value)')).toBe('mean(value) AS "test"');
     });
     });
+
+    it('should nest distinct when count is selected', () => {
+      var selectParts = [
+        queryPart.create({
+          type: 'field',
+          category: queryPart.getCategories().Fields,
+        }),
+        queryPart.create({
+          type: 'count',
+          category: queryPart.getCategories().Aggregations,
+        }),
+      ];
+      var partModel = queryPart.create({
+        type: 'distinct',
+        category: queryPart.getCategories().Aggregations,
+      });
+
+      queryPart.replaceAggregationAdd(selectParts, partModel);
+
+      expect(selectParts[1].text).toBe('distinct()');
+      expect(selectParts[2].text).toBe('count()');
+    });
+
+    it('should convert to count distinct when distinct is selected and count added', () => {
+      var selectParts = [
+        queryPart.create({
+          type: 'field',
+          category: queryPart.getCategories().Fields,
+        }),
+        queryPart.create({
+          type: 'distinct',
+          category: queryPart.getCategories().Aggregations,
+        }),
+      ];
+      var partModel = queryPart.create({
+        type: 'count',
+        category: queryPart.getCategories().Aggregations,
+      });
+
+      queryPart.replaceAggregationAdd(selectParts, partModel);
+
+      expect(selectParts[1].text).toBe('distinct()');
+      expect(selectParts[2].text).toBe('count()');
+    });
+
+    it('should replace count distinct if an aggregation is selected', () => {
+      var selectParts = [
+        queryPart.create({
+          type: 'field',
+          category: queryPart.getCategories().Fields,
+        }),
+        queryPart.create({
+          type: 'distinct',
+          category: queryPart.getCategories().Aggregations,
+        }),
+        queryPart.create({
+          type: 'count',
+          category: queryPart.getCategories().Aggregations,
+        }),
+      ];
+      var partModel = queryPart.create({
+        type: 'mean',
+        category: queryPart.getCategories().Selectors,
+      });
+
+      queryPart.replaceAggregationAdd(selectParts, partModel);
+
+      expect(selectParts[1].text).toBe('mean()');
+      expect(selectParts).toHaveLength(2);
+    });
+
+    it('should not allowed nested counts when count distinct is selected', () => {
+      var selectParts = [
+        queryPart.create({
+          type: 'field',
+          category: queryPart.getCategories().Fields,
+        }),
+        queryPart.create({
+          type: 'distinct',
+          category: queryPart.getCategories().Aggregations,
+        }),
+        queryPart.create({
+          type: 'count',
+          category: queryPart.getCategories().Aggregations,
+        }),
+      ];
+      var partModel = queryPart.create({
+        type: 'count',
+        category: queryPart.getCategories().Aggregations,
+      });
+
+      queryPart.replaceAggregationAdd(selectParts, partModel);
+
+      expect(selectParts[1].text).toBe('distinct()');
+      expect(selectParts[2].text).toBe('count()');
+      expect(selectParts).toHaveLength(3);
+    });
+
+    it('should not remove count distinct when distinct is added', () => {
+      var selectParts = [
+        queryPart.create({
+          type: 'field',
+          category: queryPart.getCategories().Fields,
+        }),
+        queryPart.create({
+          type: 'distinct',
+          category: queryPart.getCategories().Aggregations,
+        }),
+        queryPart.create({
+          type: 'count',
+          category: queryPart.getCategories().Aggregations,
+        }),
+      ];
+      var partModel = queryPart.create({
+        type: 'distinct',
+        category: queryPart.getCategories().Aggregations,
+      });
+
+      queryPart.replaceAggregationAdd(selectParts, partModel);
+
+      expect(selectParts[1].text).toBe('distinct()');
+      expect(selectParts[2].text).toBe('count()');
+      expect(selectParts).toHaveLength(3);
+    });
+
+    it('should remove distinct when sum aggregation is selected', () => {
+      var selectParts = [
+        queryPart.create({
+          type: 'field',
+          category: queryPart.getCategories().Fields,
+        }),
+        queryPart.create({
+          type: 'distinct',
+          category: queryPart.getCategories().Aggregations,
+        }),
+      ];
+      var partModel = queryPart.create({
+        type: 'sum',
+        category: queryPart.getCategories().Aggregations,
+      });
+      queryPart.replaceAggregationAdd(selectParts, partModel);
+
+      expect(selectParts[1].text).toBe('sum()');
+    });
   });
   });
 });
 });