Skip to content

Commit 77e1473

Browse files
committed
Added test cases for unnest
1 parent e1074b9 commit 77e1473

3 files changed

Lines changed: 128 additions & 10 deletions

File tree

document-store/src/integrationTest/java/org/hypertrace/core/documentstore/DocStoreQueryV1Test.java

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ private static void createFlatCollectionSchema(
192192
+ "\"price\" INTEGER,"
193193
+ "\"quantity\" INTEGER,"
194194
+ "\"date\" TIMESTAMPTZ,"
195+
+ "\"tags\" TEXT[],"
195196
+ "\"props\" JSONB,"
196197
+ "\"sales\" JSONB"
197198
+ ");",
@@ -4026,4 +4027,113 @@ void testFlatVsNestedCollectionConsistency(String dataStoreName) throws IOExcept
40264027
nestedDocIterator.close();
40274028
flatDocIterator.close();
40284029
}
4030+
4031+
// Disabling this test as unnest of top-level json fields is not supported right now
4032+
@ParameterizedTest
4033+
@ArgumentsSource(PostgresProvider.class)
4034+
@Disabled
4035+
void testFlatPostgresCollectionUnnestTags(String dataStoreName) throws IOException {
4036+
Datastore datastore = datastoreMap.get(dataStoreName);
4037+
Collection flatCollection =
4038+
datastore.getCollectionForType(FLAT_COLLECTION_NAME, DocumentType.FLAT);
4039+
4040+
// Query to unnest tags and group by them to get counts
4041+
Query unnestQuery =
4042+
Query.builder()
4043+
.addSelection(IdentifierExpression.of("tags"))
4044+
.addSelection(AggregateExpression.of(COUNT, ConstantExpression.of("*")), "count")
4045+
.addAggregation(IdentifierExpression.of("tags"))
4046+
.addFromClause(UnnestExpression.of(IdentifierExpression.of("tags"), false))
4047+
.build();
4048+
4049+
CloseableIterator<Document> iterator = flatCollection.aggregate(unnestQuery);
4050+
4051+
// Collect results
4052+
Map<String, Integer> tagCounts = new HashMap<>();
4053+
while (iterator.hasNext()) {
4054+
Document doc = iterator.next();
4055+
JsonNode json = new ObjectMapper().readTree(doc.toJson());
4056+
String tag = json.get("tags").asText();
4057+
int count = json.get("count").asInt();
4058+
tagCounts.put(tag, count);
4059+
}
4060+
iterator.close();
4061+
4062+
// Verify we have results
4063+
assertFalse(tagCounts.isEmpty(), "Should have tag counts");
4064+
4065+
// Verify some expected tag counts based on our test data
4066+
// From collection_data.json, we can verify specific tags appear expected number of times
4067+
assertTrue(tagCounts.containsKey("hygiene"), "Should contain 'hygiene' tag");
4068+
assertTrue(tagCounts.containsKey("personal-care"), "Should contain 'personal-care' tag");
4069+
assertTrue(tagCounts.containsKey("grooming"), "Should contain 'grooming' tag");
4070+
4071+
// Verify total count matches expected (each document contributes its tag count)
4072+
int totalTags = tagCounts.values().stream().mapToInt(Integer::intValue).sum();
4073+
assertTrue(totalTags > 0, "Total tag count should be greater than 0");
4074+
4075+
// Print results for debugging
4076+
System.out.println("Tag counts from unnest operation:");
4077+
tagCounts.entrySet().stream()
4078+
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
4079+
.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
4080+
}
4081+
4082+
@ParameterizedTest
4083+
@ArgumentsSource(PostgresProvider.class)
4084+
void testNestedPostgresCollectionUnnestTags(String dataStoreName) throws IOException {
4085+
Datastore datastore = datastoreMap.get(dataStoreName);
4086+
Collection nestedCollection =
4087+
datastore.getCollection(COLLECTION_NAME); // Default nested collection
4088+
4089+
// Query to unnest tags and group by them to get counts
4090+
Query unnestQuery =
4091+
Query.builder()
4092+
.addSelection(IdentifierExpression.of("tags"))
4093+
.addSelection(AggregateExpression.of(COUNT, ConstantExpression.of("*")), "count")
4094+
.addAggregation(IdentifierExpression.of("tags"))
4095+
.addFromClause(UnnestExpression.of(IdentifierExpression.of("tags"), false))
4096+
.build();
4097+
4098+
CloseableIterator<Document> iterator = nestedCollection.aggregate(unnestQuery);
4099+
4100+
// Collect results
4101+
Map<String, Integer> tagCounts = new HashMap<>();
4102+
while (iterator.hasNext()) {
4103+
Document doc = iterator.next();
4104+
JsonNode json = new ObjectMapper().readTree(doc.toJson());
4105+
String tag = json.get("tags").asText();
4106+
int count = json.get("count").asInt();
4107+
tagCounts.put(tag, count);
4108+
}
4109+
iterator.close();
4110+
4111+
// Verify we have results
4112+
assertFalse(tagCounts.isEmpty(), "Should have tag counts from nested collection");
4113+
4114+
// Verify some expected tag counts based on our test data
4115+
// From collection_data.json, we can verify specific tags appear expected number of times
4116+
assertTrue(tagCounts.containsKey("hygiene"), "Should contain 'hygiene' tag");
4117+
assertTrue(tagCounts.containsKey("personal-care"), "Should contain 'personal-care' tag");
4118+
assertTrue(tagCounts.containsKey("grooming"), "Should contain 'grooming' tag");
4119+
4120+
// Verify total count matches expected (each document contributes its tag count)
4121+
int totalTags = tagCounts.values().stream().mapToInt(Integer::intValue).sum();
4122+
assertTrue(totalTags > 0, "Total tag count should be greater than 0");
4123+
4124+
// Print results for debugging
4125+
System.out.println("Nested collection tag counts from unnest operation:");
4126+
tagCounts.entrySet().stream()
4127+
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
4128+
.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
4129+
4130+
// Verify some specific expected counts based on collection_data.json
4131+
// From looking at the data:
4132+
// - "hygiene" appears in docs 1, 5, 8 = 3 times
4133+
// - "personal-care" appears in docs 1, 3 = 2 times
4134+
// - "grooming" appears in docs 6, 7 = 2 times
4135+
assertEquals(3, tagCounts.get("hygiene"), "hygiene should appear 3 times");
4136+
assertEquals(2, tagCounts.get("personal-care"), "personal-care should appear 2 times");
4137+
assertEquals(2, tagCounts.get("grooming"), "grooming should appear 2 times");
4138+
}
40294139
}

document-store/src/integrationTest/resources/query/collection_data.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"price": 10,
66
"quantity": 2,
77
"date": "2014-03-01T08:00:00Z",
8+
"tags": ["hygiene", "personal-care", "premium"],
89
"props": {
910
"colors": [
1011
"Blue",
@@ -59,6 +60,7 @@
5960
"price": 20,
6061
"quantity": 1,
6162
"date": "2014-03-01T09:00:00Z",
63+
"tags": ["home-decor", "reflective", "glass"],
6264
"sales": [
6365
{
6466
"city": "delhi",
@@ -72,6 +74,7 @@
7274
"price": 5,
7375
"quantity": 10,
7476
"date": "2014-03-15T09:00:00Z",
77+
"tags": ["hair-care", "personal-care", "premium", "herbal"],
7578
"props": {
7679
"colors": [
7780
"Black"
@@ -129,6 +132,7 @@
129132
"price": 5,
130133
"quantity": 20,
131134
"date": "2014-04-04T11:21:39.736Z",
135+
"tags": ["hair-care", "budget", "bulk"],
132136
"sales": []
133137
},
134138
{
@@ -137,6 +141,7 @@
137141
"price": 20,
138142
"quantity": 5,
139143
"date": "2014-04-04T21:23:13.331Z",
144+
"tags": ["hygiene", "antibacterial", "family-pack"],
140145
"props": {
141146
"colors": [
142147
"Orange",
@@ -158,14 +163,16 @@
158163
"item": "Comb",
159164
"price": 7.5,
160165
"quantity": 5,
161-
"date": "2015-06-04T05:08:13Z"
166+
"date": "2015-06-04T05:08:13Z",
167+
"tags": ["grooming", "plastic", "essential"]
162168
},
163169
{
164170
"_id": 7,
165171
"item": "Comb",
166172
"price": 7.5,
167173
"quantity": 10,
168174
"date": "2015-09-10T08:43:00Z",
175+
"tags": ["grooming", "bulk", "wholesale"],
169176
"props": {
170177
"colors": [],
171178
"seller": {
@@ -182,6 +189,7 @@
182189
"item": "Soap",
183190
"price": 10,
184191
"quantity": 5,
185-
"date": "2016-02-06T20:20:13Z"
192+
"date": "2016-02-06T20:20:13Z",
193+
"tags": ["hygiene", "budget", "basic"]
186194
}
187195
]
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"statements": [
3-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"props\", \"sales\"\n) VALUES (\n1, 'Soap', 10, 2, '2014-03-01T08:00:00Z',\n'{\"colors\": [\"Blue\", \"Green\"], \"brand\": \"Dettol\", \"size\": \"M\", \"seller\": {\"name\": \"Metro Chemicals Pvt. Ltd.\", \"address\": {\"city\": \"Mumbai\", \"pincode\": 400004}}}',\nNULL\n)",
4-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"props\", \"sales\"\n) VALUES (\n2, 'Mirror', 20, 1, '2014-03-01T09:00:00Z',\nNULL,\nNULL\n)",
5-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"props\", \"sales\"\n) VALUES (\n3, 'Shampoo', 5, 10, '2014-03-15T09:00:00Z',\n'{\"colors\": [\"Black\"], \"brand\": \"Sunsilk\", \"size\": \"L\", \"seller\": {\"name\": \"Metro Chemicals Pvt. Ltd.\", \"address\": {\"city\": \"Mumbai\", \"pincode\": 400004}}}',\nNULL\n)",
6-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"props\", \"sales\"\n) VALUES (\n4, 'Shampoo', 5, 20, '2014-04-04T11:21:39.736Z',\nNULL,\nNULL\n)",
7-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"props\", \"sales\"\n) VALUES (\n5, 'Soap', 20, 5, '2014-04-04T21:23:13.331Z',\n'{\"colors\": [\"Orange\", \"Blue\"], \"brand\": \"Lifebuoy\", \"size\": \"S\", \"seller\": {\"name\": \"Hans and Co.\", \"address\": {\"city\": \"Kolkata\", \"pincode\": 700007}}}',\nNULL\n)",
8-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"props\", \"sales\"\n) VALUES (\n6, 'Comb', 7.5, 5, '2015-06-04T05:08:13Z',\nNULL,\nNULL\n)",
9-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"props\", \"sales\"\n) VALUES (\n7, 'Comb', 7.5, 10, '2015-09-10T08:43:00Z',\n'{\"colors\": [], \"seller\": {\"name\": \"Go Go Plastics\", \"address\": {\"city\": \"Kolkata\", \"pincode\": 700007}}}',\nNULL\n)",
10-
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"props\", \"sales\"\n) VALUES (\n8, 'Soap', 10, 5, '2016-02-06T20:20:13Z',\nNULL,\nNULL\n)"
3+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"tags\", \"props\", \"sales\"\n) VALUES (\n1, 'Soap', 10, 2, '2014-03-01T08:00:00Z',\n'{\"hygiene\", \"personal-care\", \"premium\"}',\n'{\"colors\": [\"Blue\", \"Green\"], \"brand\": \"Dettol\", \"size\": \"M\", \"seller\": {\"name\": \"Metro Chemicals Pvt. Ltd.\", \"address\": {\"city\": \"Mumbai\", \"pincode\": 400004}}}',\nNULL\n)",
4+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"tags\", \"props\", \"sales\"\n) VALUES (\n2, 'Mirror', 20, 1, '2014-03-01T09:00:00Z',\n'{\"home-decor\", \"reflective\", \"glass\"}',\nNULL,\nNULL\n)",
5+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"tags\", \"props\", \"sales\"\n) VALUES (\n3, 'Shampoo', 5, 10, '2014-03-15T09:00:00Z',\n'{\"hair-care\", \"personal-care\", \"premium\", \"herbal\"}',\n'{\"colors\": [\"Black\"], \"brand\": \"Sunsilk\", \"size\": \"L\", \"seller\": {\"name\": \"Metro Chemicals Pvt. Ltd.\", \"address\": {\"city\": \"Mumbai\", \"pincode\": 400004}}}',\nNULL\n)",
6+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"tags\", \"props\", \"sales\"\n) VALUES (\n4, 'Shampoo', 5, 20, '2014-04-04T11:21:39.736Z',\n'{\"hair-care\", \"budget\", \"bulk\"}',\nNULL,\nNULL\n)",
7+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"tags\", \"props\", \"sales\"\n) VALUES (\n5, 'Soap', 20, 5, '2014-04-04T21:23:13.331Z',\n'{\"hygiene\", \"antibacterial\", \"family-pack\"}',\n'{\"colors\": [\"Orange\", \"Blue\"], \"brand\": \"Lifebuoy\", \"size\": \"S\", \"seller\": {\"name\": \"Hans and Co.\", \"address\": {\"city\": \"Kolkata\", \"pincode\": 700007}}}',\nNULL\n)",
8+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"tags\", \"props\", \"sales\"\n) VALUES (\n6, 'Comb', 7.5, 5, '2015-06-04T05:08:13Z',\n'{\"grooming\", \"plastic\", \"essential\"}',\nNULL,\nNULL\n)",
9+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"tags\", \"props\", \"sales\"\n) VALUES (\n7, 'Comb', 7.5, 10, '2015-09-10T08:43:00Z',\n'{\"grooming\", \"bulk\", \"wholesale\"}',\n'{\"colors\": [], \"seller\": {\"name\": \"Go Go Plastics\", \"address\": {\"city\": \"Kolkata\", \"pincode\": 700007}}}',\nNULL\n)",
10+
"INSERT INTO \"myTestFlat\" (\n\"_id\", \"item\", \"price\", \"quantity\", \"date\", \"tags\", \"props\", \"sales\"\n) VALUES (\n8, 'Soap', 10, 5, '2016-02-06T20:20:13Z',\n'{\"hygiene\", \"budget\", \"basic\"}',\nNULL,\nNULL\n)"
1111
]
1212
}

0 commit comments

Comments
 (0)