Pārlūkot izejas kodu

Move sum&avg composite index tests to FIRCompositeIndexQueryTests.mm (#11985)

Mila 2 gadi atpakaļ
vecāks
revīzija
8881200e68

+ 0 - 225
Firestore/Example/Tests/Integration/API/FIRAggregateTests.mm

@@ -469,61 +469,6 @@
       [NSNumber numberWithLong:150L], );
 }
 
-- (void)testCanPerformMaxAggregations {
-  XCTSkipIf(![FSTIntegrationTestCase isRunningAgainstEmulator],
-            "Skip this test if running against production because it requires a composite index.");
-  FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
-    @"a" : @{
-      @"author" : @"authorA",
-      @"title" : @"titleA",
-      @"pages" : @100,
-      @"height" : @24.5,
-      @"weight" : @24.1,
-      @"foo" : @1,
-      @"bar" : @2,
-      @"baz" : @3
-    },
-    @"b" : @{
-      @"author" : @"authorB",
-      @"title" : @"titleB",
-      @"pages" : @50,
-      @"height" : @25.5,
-      @"weight" : @75.5,
-      @"foo" : @1,
-      @"bar" : @2,
-      @"baz" : @3
-    }
-  }];
-
-  // Max is 5, do not exceed
-  FIRAggregateQuerySnapshot* snapshot =
-      [self readSnapshotForAggregate:[testCollection aggregate:@[
-              [FIRAggregateField aggregateFieldForCount],
-              [FIRAggregateField aggregateFieldForSumOfField:@"pages"],
-              [FIRAggregateField aggregateFieldForSumOfField:@"weight"],
-              [FIRAggregateField aggregateFieldForAverageOfField:@"pages"],
-              [FIRAggregateField aggregateFieldForAverageOfField:@"weight"]
-            ]]];
-
-  // Assert
-  XCTAssertEqual([snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]],
-                 [NSNumber numberWithLong:2L]);
-  XCTAssertEqual(
-      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"pages"]],
-      [NSNumber numberWithLong:150L], );
-  XCTAssertEqual(
-      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"weight"]]
-          doubleValue],
-      99.6);
-  XCTAssertEqual([snapshot valueForAggregateField:[FIRAggregateField
-                                                      aggregateFieldForAverageOfField:@"pages"]],
-                 [NSNumber numberWithDouble:75.0]);
-  XCTAssertEqual([[snapshot valueForAggregateField:[FIRAggregateField
-                                                       aggregateFieldForAverageOfField:@"weight"]]
-                     doubleValue],
-                 49.8);
-}
-
 - (void)testCannotPerformMoreThanMaxAggregations {
   FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
     @"a" : @{
@@ -574,105 +519,6 @@
   XCTAssertTrue([[result localizedDescription] containsString:@"maximum number of aggregations"]);
 }
 
-- (void)testCanRunAggregateCollectionGroupQuery {
-  XCTSkipIf(![FSTIntegrationTestCase isRunningAgainstEmulator],
-            "Skip this test if running against production because it requires a composite index.");
-
-  NSString* collectionGroup =
-      [NSString stringWithFormat:@"%@%@", @"b",
-                                 [self.db collectionWithPath:@"foo"].documentWithAutoID.documentID];
-  NSArray* docPathFormats = @[
-    @"abc/123/%@/cg-doc1", @"abc/123/%@/cg-doc2", @"%@/cg-doc3", @"%@/cg-doc4",
-    @"def/456/%@/cg-doc5", @"%@/virtual-doc/nested-coll/not-cg-doc", @"x%@/not-cg-doc",
-    @"%@x/not-cg-doc", @"abc/123/%@x/not-cg-doc", @"abc/123/x%@/not-cg-doc", @"abc/%@"
-  ];
-
-  FIRWriteBatch* batch = self.db.batch;
-  for (NSString* format in docPathFormats) {
-    NSString* path = [NSString stringWithFormat:format, collectionGroup];
-    [batch setData:@{@"x" : @2} forDocument:[self.db documentWithPath:path]];
-  }
-  [self commitWriteBatch:batch];
-
-  FIRAggregateQuerySnapshot* snapshot =
-      [self readSnapshotForAggregate:[[self.db collectionGroupWithID:collectionGroup] aggregate:@[
-              [FIRAggregateField aggregateFieldForCount],
-              [FIRAggregateField aggregateFieldForSumOfField:@"x"],
-              [FIRAggregateField aggregateFieldForAverageOfField:@"x"]
-            ]]];
-  // "cg-doc1", "cg-doc2", "cg-doc3", "cg-doc4", "cg-doc5",
-  XCTAssertEqual([snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]],
-                 [NSNumber numberWithLong:5L]);
-  XCTAssertEqual(
-      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"x"]],
-      [NSNumber numberWithLong:10L]);
-  XCTAssertEqual(
-      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"x"]],
-      [NSNumber numberWithDouble:2.0]);
-}
-
-- (void)testPerformsAggregationsWhenNaNExistsForSomeFieldValues {
-  XCTSkipIf(![FSTIntegrationTestCase isRunningAgainstEmulator],
-            "Skip this test if running against production because it requires a composite index.");
-
-  FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
-    @"a" : @{
-      @"author" : @"authorA",
-      @"title" : @"titleA",
-      @"pages" : @100,
-      @"year" : @1980,
-      @"rating" : @5
-    },
-    @"b" : @{
-      @"author" : @"authorB",
-      @"title" : @"titleB",
-      @"pages" : @50,
-      @"year" : @2020,
-      @"rating" : @4
-    },
-    @"c" : @{
-      @"author" : @"authorC",
-      @"title" : @"titleC",
-      @"pages" : @100,
-      @"year" : @1980,
-      @"rating" : [NSNumber numberWithFloat:NAN]
-    },
-    @"d" : @{
-      @"author" : @"authorD",
-      @"title" : @"titleD",
-      @"pages" : @50,
-      @"year" : @2020,
-      @"rating" : @0
-    }
-  }];
-
-  FIRAggregateQuerySnapshot* snapshot =
-      [self readSnapshotForAggregate:[testCollection aggregate:@[
-              [FIRAggregateField aggregateFieldForSumOfField:@"rating"],
-              [FIRAggregateField aggregateFieldForSumOfField:@"pages"],
-              [FIRAggregateField aggregateFieldForAverageOfField:@"rating"],
-              [FIRAggregateField aggregateFieldForAverageOfField:@"year"]
-            ]]];
-
-  // Sum
-  XCTAssertEqual(
-      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"rating"]],
-      [NSNumber numberWithDouble:NAN]);
-  XCTAssertEqual(
-      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"pages"]]
-          longValue],
-      300L);
-
-  // Average
-  XCTAssertEqual([snapshot valueForAggregateField:[FIRAggregateField
-                                                      aggregateFieldForAverageOfField:@"rating"]],
-                 [NSNumber numberWithDouble:NAN]);
-  XCTAssertEqual(
-      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"year"]]
-          doubleValue],
-      2000.0);
-}
-
 - (void)testThrowsAnErrorWhenGettingTheResultOfAnUnrequestedAggregation {
   FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
     @"a" : @{
@@ -789,77 +635,6 @@
                  4.0);
 }
 
-- (void)testPerformsAggregationWhenUsingArrayContainsAnyOperator {
-  XCTSkipIf(![FSTIntegrationTestCase isRunningAgainstEmulator],
-            "Skip this test if running against production because it requires a composite index.");
-
-  FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
-    @"a" : @{
-      @"author" : @"authorA",
-      @"title" : @"titleA",
-      @"pages" : @100,
-      @"year" : @1980,
-      @"rating" : @[ @5, @1000 ]
-    },
-    @"b" : @{
-      @"author" : @"authorB",
-      @"title" : @"titleB",
-      @"pages" : @50,
-      @"year" : @2020,
-      @"rating" : @[ @4 ]
-    },
-    @"c" : @{
-      @"author" : @"authorC",
-      @"title" : @"titleC",
-      @"pages" : @100,
-      @"year" : @1980,
-      @"rating" : @[ @2222, @3 ]
-    },
-    @"d" : @{
-      @"author" : @"authorD",
-      @"title" : @"titleD",
-      @"pages" : @50,
-      @"year" : @2020,
-      @"rating" : @[ @0 ]
-    }
-  }];
-
-  FIRAggregateQuerySnapshot* snapshot = [self
-      readSnapshotForAggregate:[[testCollection queryWhereField:@"rating"
-                                               arrayContainsAny:@[ @5, @3 ]]
-                                   aggregate:@[
-                                     [FIRAggregateField aggregateFieldForSumOfField:@"rating"],
-                                     [FIRAggregateField aggregateFieldForSumOfField:@"pages"],
-                                     [FIRAggregateField aggregateFieldForAverageOfField:@"rating"],
-                                     [FIRAggregateField aggregateFieldForAverageOfField:@"pages"],
-                                     [FIRAggregateField aggregateFieldForCount]
-                                   ]]];
-
-  // Count
-  XCTAssertEqual(
-      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]] longValue], 2L);
-
-  // Sum
-  XCTAssertEqual(
-      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"rating"]]
-          longValue],
-      0L);
-  XCTAssertEqual(
-      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"pages"]]
-          longValue],
-      200L);
-
-  // Average
-  XCTAssertEqualObjects(
-      [snapshot
-          valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"rating"]],
-      [NSNull null]);
-  XCTAssertEqual(
-      [[snapshot valueForAggregateField:[FIRAggregateField
-                                            aggregateFieldForAverageOfField:@"pages"]] doubleValue],
-      100.0);
-}
-
 - (void)testPerformsAggregationsOnNestedMapValues {
   FIRCollectionReference* testCollection = [self collectionRefWithDocuments:@{
     @"a" : @{

+ 214 - 0
Firestore/Example/Tests/Integration/API/FIRCompositeIndexQueryTests.mm

@@ -189,6 +189,10 @@ static NSString *const COMPOSITE_INDEX_TEST_COLLECTION = @"composite-index-test-
  * To get started, please refer to the instructions provided in the README file. This will
  * guide you through setting up your local testing environment and updating the Terraform
  * configuration with any new composite indexes required for your testing scenarios.
+ *
+ * Note: Whenever feasible, make use of the current document fields (such as 'a,' 'b,' 'author,'
+ * 'title') to avoid introducing new composite indexes and surpassing the limit. Refer to the
+ * guidelines at https://firebase.google.com/docs/firestore/quotas#indexes for further information.
  */
 
 - (void)testOrQueriesWithCompositeIndexes {
@@ -249,6 +253,216 @@ static NSString *const COMPOSITE_INDEX_TEST_COLLECTION = @"composite-index-test-
                               expectedDocs:@[ @"doc2" ]];
 }
 
+- (void)testCanRunAggregateCollectionGroupQuery {
+  NSString *collectionGroup = [[self testCollectionRef] collectionID];
+  NSArray *docPathFormats = @[
+    @"abc/123/%@/cg-doc1", @"abc/123/%@/cg-doc2", @"%@/cg-doc3", @"%@/cg-doc4",
+    @"def/456/%@/cg-doc5", @"%@/virtual-doc/nested-coll/not-cg-doc", @"x%@/not-cg-doc",
+    @"%@x/not-cg-doc", @"abc/123/%@x/not-cg-doc", @"abc/123/x%@/not-cg-doc", @"abc/%@"
+  ];
+
+  FIRWriteBatch *batch = self.db.batch;
+  for (NSString *format in docPathFormats) {
+    NSString *path = [NSString stringWithFormat:format, collectionGroup];
+    [batch setData:[self addTestSpecificFieldsToDoc:@{@"a" : @2}]
+        forDocument:[self.db documentWithPath:path]];
+  }
+  [self commitWriteBatch:batch];
+
+  FIRAggregateQuerySnapshot *snapshot = [self
+      readSnapshotForAggregate:[[self
+                                   compositeIndexQuery:[self.db
+                                                           collectionGroupWithID:collectionGroup]]
+                                   aggregate:@[
+                                     [FIRAggregateField aggregateFieldForCount],
+                                     [FIRAggregateField aggregateFieldForSumOfField:@"a"],
+                                     [FIRAggregateField aggregateFieldForAverageOfField:@"a"]
+                                   ]]];
+  // "cg-doc1", "cg-doc2", "cg-doc3", "cg-doc4", "cg-doc5",
+  XCTAssertEqual([snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]],
+                 [NSNumber numberWithLong:5L]);
+  XCTAssertEqual(
+      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"a"]],
+      [NSNumber numberWithLong:10L]);
+  XCTAssertEqual(
+      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"a"]],
+      [NSNumber numberWithDouble:2.0]);
+}
+
+- (void)testCanPerformMaxAggregations {
+  FIRCollectionReference *testCollection = [self withTestDocs:@{
+    @"a" : @{
+      @"author" : @"authorA",
+      @"title" : @"titleA",
+      @"pages" : @100,
+      @"year" : @1980,
+      @"rating" : @5.0,
+    },
+    @"b" : @{
+      @"author" : @"authorB",
+      @"title" : @"titleB",
+      @"pages" : @50,
+      @"year" : @2020,
+      @"rating" : @4.0,
+    }
+  }];
+
+  // Max is 5, do not exceed
+  FIRAggregateQuerySnapshot *snapshot =
+      [self readSnapshotForAggregate:[[self compositeIndexQuery:testCollection] aggregate:@[
+              [FIRAggregateField aggregateFieldForCount],
+              [FIRAggregateField aggregateFieldForSumOfField:@"pages"],
+              [FIRAggregateField aggregateFieldForSumOfField:@"year"],
+              [FIRAggregateField aggregateFieldForAverageOfField:@"pages"],
+              [FIRAggregateField aggregateFieldForAverageOfField:@"rating"]
+            ]]];
+
+  // Assert
+  XCTAssertEqual([snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]],
+                 [NSNumber numberWithLong:2L]);
+  XCTAssertEqual(
+      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"pages"]],
+      [NSNumber numberWithLong:150L]);
+  XCTAssertEqual(
+      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"year"]],
+      [NSNumber numberWithLong:4000L]);
+  XCTAssertEqual([snapshot valueForAggregateField:[FIRAggregateField
+                                                      aggregateFieldForAverageOfField:@"pages"]],
+                 [NSNumber numberWithDouble:75.0]);
+  XCTAssertEqual([[snapshot valueForAggregateField:[FIRAggregateField
+                                                       aggregateFieldForAverageOfField:@"rating"]]
+                     doubleValue],
+                 4.5);
+}
+
+- (void)testPerformsAggregationsWhenNaNExistsForSomeFieldValues {
+  FIRCollectionReference *testCollection = [self withTestDocs:@{
+    @"a" : @{
+      @"author" : @"authorA",
+      @"title" : @"titleA",
+      @"pages" : @100,
+      @"year" : @1980,
+      @"rating" : @5
+    },
+    @"b" : @{
+      @"author" : @"authorB",
+      @"title" : @"titleB",
+      @"pages" : @50,
+      @"year" : @2020,
+      @"rating" : @4
+    },
+    @"c" : @{
+      @"author" : @"authorC",
+      @"title" : @"titleC",
+      @"pages" : @100,
+      @"year" : @1980,
+      @"rating" : [NSNumber numberWithFloat:NAN]
+    },
+    @"d" : @{
+      @"author" : @"authorD",
+      @"title" : @"titleD",
+      @"pages" : @50,
+      @"year" : @2020,
+      @"rating" : @0
+    }
+  }];
+
+  FIRAggregateQuerySnapshot *snapshot =
+      [self readSnapshotForAggregate:[[self compositeIndexQuery:testCollection] aggregate:@[
+              [FIRAggregateField aggregateFieldForSumOfField:@"rating"],
+              [FIRAggregateField aggregateFieldForSumOfField:@"pages"],
+              [FIRAggregateField aggregateFieldForAverageOfField:@"rating"],
+              [FIRAggregateField aggregateFieldForAverageOfField:@"year"]
+            ]]];
+
+  // Sum
+  XCTAssertEqual(
+      [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"rating"]],
+      [NSNumber numberWithDouble:NAN]);
+  XCTAssertEqual(
+      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"pages"]]
+          longValue],
+      300L);
+
+  // Average
+  XCTAssertEqual([snapshot valueForAggregateField:[FIRAggregateField
+                                                      aggregateFieldForAverageOfField:@"rating"]],
+                 [NSNumber numberWithDouble:NAN]);
+  XCTAssertEqual(
+      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"year"]]
+          doubleValue],
+      2000.0);
+}
+
+- (void)testPerformsAggregationWhenUsingArrayContainsAnyOperator {
+  FIRCollectionReference *testCollection = [self withTestDocs:@{
+    @"a" : @{
+      @"author" : @"authorA",
+      @"title" : @"titleA",
+      @"pages" : @100,
+      @"year" : @1980,
+      @"rating" : @[ @5, @1000 ]
+    },
+    @"b" : @{
+      @"author" : @"authorB",
+      @"title" : @"titleB",
+      @"pages" : @50,
+      @"year" : @2020,
+      @"rating" : @[ @4 ]
+    },
+    @"c" : @{
+      @"author" : @"authorC",
+      @"title" : @"titleC",
+      @"pages" : @100,
+      @"year" : @1980,
+      @"rating" : @[ @2222, @3 ]
+    },
+    @"d" : @{
+      @"author" : @"authorD",
+      @"title" : @"titleD",
+      @"pages" : @50,
+      @"year" : @2020,
+      @"rating" : @[ @0 ]
+    }
+  }];
+
+  FIRAggregateQuerySnapshot *snapshot = [self
+      readSnapshotForAggregate:[[self
+                                   compositeIndexQuery:[testCollection queryWhereField:@"rating"
+                                                                      arrayContainsAny:@[ @5, @3 ]]]
+                                   aggregate:@[
+                                     [FIRAggregateField aggregateFieldForSumOfField:@"rating"],
+                                     [FIRAggregateField aggregateFieldForSumOfField:@"pages"],
+                                     [FIRAggregateField aggregateFieldForAverageOfField:@"rating"],
+                                     [FIRAggregateField aggregateFieldForAverageOfField:@"pages"],
+                                     [FIRAggregateField aggregateFieldForCount]
+                                   ]]];
+
+  // Count
+  XCTAssertEqual(
+      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]] longValue], 2L);
+
+  // Sum
+  XCTAssertEqual(
+      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"rating"]]
+          longValue],
+      0L);
+  XCTAssertEqual(
+      [[snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"pages"]]
+          longValue],
+      200L);
+
+  // Average
+  XCTAssertEqualObjects(
+      [snapshot
+          valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"rating"]],
+      [NSNull null]);
+  XCTAssertEqual(
+      [[snapshot valueForAggregateField:[FIRAggregateField
+                                            aggregateFieldForAverageOfField:@"pages"]] doubleValue],
+      100.0);
+}
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 14 - 0
Firestore/firestore_collection_group_index_config.tf

@@ -0,0 +1,14 @@
+locals {
+  collection_group_indexes = {
+    index1 = [
+      {
+        field_path = "testId"
+        order      = "ASCENDING"
+      },
+      {
+        field_path = "a"
+        order      = "ASCENDING"
+      },
+    ]
+  }
+}

+ 50 - 0
Firestore/firestore_index_config.tf → Firestore/firestore_composite_index_config.tf

@@ -100,5 +100,55 @@ locals {
         order      = "DESCENDING"
       },
     ]
+    index9 = [
+      {
+        field_path = "testId"
+        order      = "ASCENDING"
+      },
+      {
+        field_path = "pages"
+        order      = "ASCENDING"
+      },
+      {
+        field_path = "year"
+        order      = "ASCENDING"
+      },
+    ]
+    index10 = [
+      {
+        field_path = "testId"
+        order      = "ASCENDING"
+      },
+      {
+        field_path = "pages"
+        order      = "ASCENDING"
+      },
+      {
+        field_path = "rating"
+        order      = "ASCENDING"
+      },
+      {
+        field_path = "year"
+        order      = "ASCENDING"
+      },
+    ]
+    index11 = [
+      {
+        field_path   = "rating"
+        array_config = "CONTAINS"
+      },
+      {
+        field_path = "testId"
+        order      = "ASCENDING"
+      },
+      {
+        field_path = "pages"
+        order      = "ASCENDING"
+      },
+      {
+        field_path = "rating"
+        order      = "ASCENDING"
+      },
+    ]
   }
 }

+ 55 - 10
Firestore/main.tf

@@ -4,24 +4,46 @@ provider "google" {
   project = var.project_id
 }
 
-resource "google_firestore_index" "default-db-index" {
+resource "google_firestore_index" "default_db_index" {
   collection = "composite-index-test-collection"
 
   for_each = local.indexes
   dynamic "fields" {
     for_each = distinct(flatten([for k, v in local.indexes : [
       for i in each.value : {
-        field_path = i.field_path
-        order      = i.order
+        field_path   = i.field_path
+        order        = can(i.order) ? i.order : null
+        array_config = can(i.array_config) ? i.array_config : null
     }]]))
     content {
-      field_path = lookup(fields.value, "field_path", null)
-      order      = lookup(fields.value, "order", null)
+      field_path   = fields.value.field_path
+      order        = fields.value.order
+      array_config = fields.value.array_config
     }
   }
 }
 
-resource "google_firestore_index" "named-db-index" {
+resource "google_firestore_index" "default_db_collection_group_index" {
+  collection  = "composite-index-test-collection"
+  query_scope = "COLLECTION_GROUP"
+
+  for_each = local.collection_group_indexes
+  dynamic "fields" {
+    for_each = distinct(flatten([for k, v in local.indexes : [
+      for i in each.value : {
+        field_path   = i.field_path
+        order        = can(i.order) ? i.order : null
+        array_config = can(i.array_config) ? i.array_config : null
+    }]]))
+    content {
+      field_path   = fields.value.field_path
+      order        = fields.value.order
+      array_config = fields.value.array_config
+    }
+  }
+}
+
+resource "google_firestore_index" "named_db_index" {
   collection = "composite-index-test-collection"
   database   = "test-db"
 
@@ -29,12 +51,35 @@ resource "google_firestore_index" "named-db-index" {
   dynamic "fields" {
     for_each = distinct(flatten([for k, v in local.indexes : [
       for i in each.value : {
-        field_path = i.field_path
-        order      = i.order
+        field_path   = i.field_path
+        order        = can(i.order) ? i.order : null
+        array_config = can(i.array_config) ? i.array_config : null
+    }]]))
+    content {
+      field_path   = fields.value.field_path
+      order        = fields.value.order
+      array_config = fields.value.array_config
+    }
+  }
+}
+
+resource "google_firestore_index" "named_db_collection_group_index" {
+  collection  = "composite-index-test-collection"
+  database    = "test-db"
+  query_scope = "COLLECTION_GROUP"
+
+  for_each = local.collection_group_indexes
+  dynamic "fields" {
+    for_each = distinct(flatten([for k, v in local.indexes : [
+      for i in each.value : {
+        field_path   = i.field_path
+        order        = can(i.order) ? i.order : null
+        array_config = can(i.array_config) ? i.array_config : null
     }]]))
     content {
-      field_path = lookup(fields.value, "field_path", null)
-      order      = lookup(fields.value, "order", null)
+      field_path   = fields.value.field_path
+      order        = fields.value.order
+      array_config = fields.value.array_config
     }
   }
 }