From bd180c34ccebecd9cbb0afa7dc8885ee4e7a0159 Mon Sep 17 00:00:00 2001 From: mudaafi Date: Tue, 11 Nov 2025 07:24:19 +0800 Subject: [PATCH 1/3] add new aggregation functions values --- .../io/constructor/client/VariationsMap.java | 6 + .../constructor/client/VariationsMapTest.java | 117 ++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 constructorio-client/src/test/java/io/constructor/client/VariationsMapTest.java diff --git a/constructorio-client/src/main/java/io/constructor/client/VariationsMap.java b/constructorio-client/src/main/java/io/constructor/client/VariationsMap.java index 34198df5..ca686d83 100644 --- a/constructorio-client/src/main/java/io/constructor/client/VariationsMap.java +++ b/constructorio-client/src/main/java/io/constructor/client/VariationsMap.java @@ -53,6 +53,12 @@ public enum AggregationTypes { max, @SerializedName("all") all, + @SerializedName("count") + count, + @SerializedName("field_count") + field_count, + @SerializedName("value_count") + value_count, } @SerializedName("dtype") diff --git a/constructorio-client/src/test/java/io/constructor/client/VariationsMapTest.java b/constructorio-client/src/test/java/io/constructor/client/VariationsMapTest.java new file mode 100644 index 00000000..4ab483a9 --- /dev/null +++ b/constructorio-client/src/test/java/io/constructor/client/VariationsMapTest.java @@ -0,0 +1,117 @@ +package io.constructor.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.junit.Test; + +public class VariationsMapTest { + + @Test + public void newShouldReturnVariationsMap() throws Exception { + VariationsMap variationsMap = new VariationsMap(); + assertNotNull(variationsMap); + assertEquals(variationsMap.getdType(), VariationsMap.Dtypes.array); + } + + @Test + public void addGroupByRuleShouldAddRule() throws Exception { + VariationsMap variationsMap = new VariationsMap(); + variationsMap.addGroupByRule("variation", "data.variation_id"); + assertEquals(variationsMap.getGroupBy().size(), 1); + assertEquals(variationsMap.getGroupBy().get(0).name, "variation"); + assertEquals(variationsMap.getGroupBy().get(0).field, "data.variation_id"); + } + + @Test + public void addValueRuleShouldAddRule() throws Exception { + VariationsMap variationsMap = new VariationsMap(); + variationsMap.addValueRule( + "size", VariationsMap.AggregationTypes.first, "data.facets.size"); + assertEquals(variationsMap.getValues().size(), 1); + assertEquals( + variationsMap.getValues().get("size").aggregation, + VariationsMap.AggregationTypes.first); + assertEquals(variationsMap.getValues().get("size").field, "data.facets.size"); + } + + @Test + public void allAggregationTypesShouldSerializeCorrectly() throws Exception { + VariationsMap variationsMap = new VariationsMap(); + variationsMap.addValueRule( + "size", VariationsMap.AggregationTypes.first, "data.facets.size"); + variationsMap.addValueRule( + "min_price", VariationsMap.AggregationTypes.min, "data.facets.price"); + variationsMap.addValueRule( + "max_price", VariationsMap.AggregationTypes.max, "data.facets.price"); + variationsMap.addValueRule("tags", VariationsMap.AggregationTypes.all, "data.facets.tags"); + variationsMap.addValueRule( + "variation_count", VariationsMap.AggregationTypes.count, "data.variation_id"); + variationsMap.addValueRule( + "color_count", VariationsMap.AggregationTypes.field_count, "data.facets.color"); + variationsMap.addValueRule( + "blue_count", VariationsMap.AggregationTypes.value_count, "data.facets.color"); + + Gson gson = new Gson(); + String json = gson.toJson(variationsMap); + JsonObject jsonObj = gson.fromJson(json, JsonObject.class); + + // Verify all aggregation types are serialized correctly in JSON string + assertTrue(json.contains("\"aggregation\":\"first\"")); + assertTrue(json.contains("\"aggregation\":\"min\"")); + assertTrue(json.contains("\"aggregation\":\"max\"")); + assertTrue(json.contains("\"aggregation\":\"all\"")); + assertTrue(json.contains("\"aggregation\":\"count\"")); + assertTrue(json.contains("\"aggregation\":\"field_count\"")); + assertTrue(json.contains("\"aggregation\":\"value_count\"")); + + // Verify each aggregation type is correctly deserialized + assertEquals( + jsonObj.getAsJsonObject("values") + .getAsJsonObject("size") + .get("aggregation") + .getAsString(), + "first"); + assertEquals( + jsonObj.getAsJsonObject("values") + .getAsJsonObject("min_price") + .get("aggregation") + .getAsString(), + "min"); + assertEquals( + jsonObj.getAsJsonObject("values") + .getAsJsonObject("max_price") + .get("aggregation") + .getAsString(), + "max"); + assertEquals( + jsonObj.getAsJsonObject("values") + .getAsJsonObject("tags") + .get("aggregation") + .getAsString(), + "all"); + assertEquals( + jsonObj.getAsJsonObject("values") + .getAsJsonObject("variation_count") + .get("aggregation") + .getAsString(), + "count"); + assertEquals( + jsonObj.getAsJsonObject("values") + .getAsJsonObject("color_count") + .get("aggregation") + .getAsString(), + "field_count"); + assertEquals( + jsonObj.getAsJsonObject("values") + .getAsJsonObject("blue_count") + .get("aggregation") + .getAsString(), + "value_count"); + + assertEquals(variationsMap.getValues().size(), 7); + } +} From 8c4d023aa14c9adad1f402071b65c6e7cda9d4c1 Mon Sep 17 00:00:00 2001 From: mudaafi Date: Tue, 11 Nov 2025 08:44:06 +0800 Subject: [PATCH 2/3] serialize variation_slice --- .../io/constructor/client/models/Result.java | 14 +++++ .../client/BrowseResponseTest.java | 28 ++++++++++ .../client/SearchResponseTest.java | 28 ++++++++++ .../response.browse.variation_slice.json | 52 +++++++++++++++++++ .../response.search.variation_slice.json | 49 +++++++++++++++++ 5 files changed, 171 insertions(+) create mode 100644 constructorio-client/src/test/resources/response.browse.variation_slice.json create mode 100644 constructorio-client/src/test/resources/response.search.variation_slice.json diff --git a/constructorio-client/src/main/java/io/constructor/client/models/Result.java b/constructorio-client/src/main/java/io/constructor/client/models/Result.java index ed2ec1e8..11b99e36 100644 --- a/constructorio-client/src/main/java/io/constructor/client/models/Result.java +++ b/constructorio-client/src/main/java/io/constructor/client/models/Result.java @@ -22,6 +22,9 @@ public class Result { @SerializedName("variations_map") private Object variationsMap; + @SerializedName("variation_slice") + private Map> variationSlice; + @SerializedName("is_slotted") private boolean isSlotted; @@ -80,6 +83,13 @@ public Map getStrategy() { return strategy; } + /** + * @return the variationSlice + */ + public Map> getVariationSlice() { + return variationSlice; + } + /** * @return isSlotted boolean */ @@ -115,6 +125,10 @@ public void setStrategy(Map strategy) { this.strategy = strategy; } + public void setVariationSlice(Map> variationSlice) { + this.variationSlice = variationSlice; + } + public void setIsSlotted(boolean isSlotted) { this.isSlotted = isSlotted; } diff --git a/constructorio-client/src/test/java/io/constructor/client/BrowseResponseTest.java b/constructorio-client/src/test/java/io/constructor/client/BrowseResponseTest.java index 3357bb48..59bb65ba 100644 --- a/constructorio-client/src/test/java/io/constructor/client/BrowseResponseTest.java +++ b/constructorio-client/src/test/java/io/constructor/client/BrowseResponseTest.java @@ -1,6 +1,8 @@ package io.constructor.client; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import io.constructor.client.models.BrowseResponse; @@ -48,6 +50,9 @@ public void createBrowseResponseShouldReturnAResult() throws Exception { "total number of results", (int) response.getResponse().getTotalNumberOfResults(), 562); + assertNull( + "variation_slice should be null when not present", + response.getResponse().getResults().get(0).getVariationSlice()); assertTrue( "browse result labels exists", (Boolean) @@ -332,4 +337,27 @@ public void createBrowseResponseShouldReturnAResultWithFeatures() throws Excepti response.getResponse().getFeatures().get(1).getVariant(), null); } + + @Test + public void createBrowseResponseShouldReturnAResultWithVariationSlice() throws Exception { + String string = Utils.getTestResource("response.browse.variation_slice.json"); + BrowseResponse response = ConstructorIO.createBrowseResponse(string); + + // Results should have variation_slice with one variation_id + assertNotNull( + "variation_slice should exist", + response.getResponse().getResults().get(0).getVariationSlice()); + assertNotNull( + "variation_id key should exist", + response.getResponse().getResults().get(0).getVariationSlice().get("variation_id")); + assertEquals( + "variation_id should match", + response.getResponse() + .getResults() + .get(0) + .getVariationSlice() + .get("variation_id") + .get(0), + "901764002"); + } } diff --git a/constructorio-client/src/test/java/io/constructor/client/SearchResponseTest.java b/constructorio-client/src/test/java/io/constructor/client/SearchResponseTest.java index 57a9e161..477592f2 100644 --- a/constructorio-client/src/test/java/io/constructor/client/SearchResponseTest.java +++ b/constructorio-client/src/test/java/io/constructor/client/SearchResponseTest.java @@ -1,6 +1,8 @@ package io.constructor.client; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import io.constructor.client.models.SearchResponse; @@ -40,6 +42,9 @@ public void createSearchResponseShouldReturnAResult() throws Exception { "total number of results", (int) response.getResponse().getTotalNumberOfResults(), 301); + assertNull( + "variation_slice should be null when not present", + response.getResponse().getResults().get(0).getVariationSlice()); assertTrue("search result id exists", response.getResultId() != null); assertTrue("request exists", response.getRequest() != null); assertEquals("request query exists", response.getRequest().get("term"), "peanut"); @@ -308,4 +313,27 @@ public void createSearchResponseShouldReturnAResultWithFeatures() throws Excepti response.getResponse().getFeatures().get(2).getVariant(), null); } + + @Test + public void createSearchResponseShouldReturnAResultWithVariationSlice() throws Exception { + String string = Utils.getTestResource("response.search.variation_slice.json"); + SearchResponse response = ConstructorIO.createSearchResponse(string); + + // Results should have variation_slice with one variation_id + assertNotNull( + "variation_slice should exist", + response.getResponse().getResults().get(0).getVariationSlice()); + assertNotNull( + "variation_id key should exist", + response.getResponse().getResults().get(0).getVariationSlice().get("variation_id")); + assertEquals( + "variation_id should match", + response.getResponse() + .getResults() + .get(0) + .getVariationSlice() + .get("variation_id") + .get(0), + "801764002"); + } } diff --git a/constructorio-client/src/test/resources/response.browse.variation_slice.json b/constructorio-client/src/test/resources/response.browse.variation_slice.json new file mode 100644 index 00000000..e8556504 --- /dev/null +++ b/constructorio-client/src/test/resources/response.browse.variation_slice.json @@ -0,0 +1,52 @@ +{ + "response": { + "facets": [], + "groups": [], + "results": [{ + "matched_terms": [], + "data": { + "id": "20001", + "url": "https://test.com/p/20001", + "facets": [{ + "name": "Color", + "values": ["blue"] + }], + "image_url": "https://test.com/p/20001", + "description": "browse item with variation_slice", + "deactivated": false + }, + "value": "BrowseItem1", + "is_slotted": false, + "labels": {}, + "variation_slice": { + "variation_id": ["901764002"] + } + }, { + "matched_terms": [], + "data": { + "id": "20002", + "url": "https://test.com/p/20002", + "facets": [{ + "name": "Color", + "values": ["blue"] + }], + "image_url": "https://test.com/p/20002", + "description": "browse item with variation_slice", + "deactivated": false + }, + "value": "BrowseItem2", + "is_slotted": false, + "labels": {}, + "variation_slice": { + "variation_id": ["904422022"] + } + }], + "total_num_results": 2, + "result_id": "test-browse-result-id" + }, + "result_id": "test-browse-result-id", + "request": { + "browse_filter_name": "Color", + "browse_filter_value": "Blue" + } +} diff --git a/constructorio-client/src/test/resources/response.search.variation_slice.json b/constructorio-client/src/test/resources/response.search.variation_slice.json new file mode 100644 index 00000000..7a9b0097 --- /dev/null +++ b/constructorio-client/src/test/resources/response.search.variation_slice.json @@ -0,0 +1,49 @@ +{ + "response": { + "facets": [], + "groups": [], + "results": [{ + "matched_terms": ["item"], + "data": { + "id": "10001", + "url": "https://test.com/p/10001", + "facets": [{ + "name": "Price", + "values": [30] + }], + "image_url": "https://test.com/p/10001", + "description": "item with variation_slice", + "deactivated": false + }, + "value": "Item1", + "is_slotted": false, + "labels": {}, + "variation_slice": { + "variation_id": ["801764002"] + } + }, { + "matched_terms": ["item"], + "data": { + "id": "10002", + "url": "https://test.com/p/10002", + "facets": [{ + "name": "Price", + "values": [20] + }], + "image_url": "https://test.com/p/10002", + "description": "item with variation_slice", + "deactivated": false + }, + "value": "Item2", + "is_slotted": false, + "labels": {}, + "variation_slice": { + "variation_id": ["804422022"] + } + }], + "total_num_results": 2, + "result_id": "test-result-id" + }, + "result_id": "test-result-id", + "request": {} +} From efaec7fab01f38706fbad1614998f441e074ec94 Mon Sep 17 00:00:00 2001 From: mudaafi Date: Tue, 11 Nov 2025 08:55:05 +0800 Subject: [PATCH 3/3] add future note --- .../src/main/java/io/constructor/client/models/Result.java | 1 + 1 file changed, 1 insertion(+) diff --git a/constructorio-client/src/main/java/io/constructor/client/models/Result.java b/constructorio-client/src/main/java/io/constructor/client/models/Result.java index 11b99e36..a754b41f 100644 --- a/constructorio-client/src/main/java/io/constructor/client/models/Result.java +++ b/constructorio-client/src/main/java/io/constructor/client/models/Result.java @@ -22,6 +22,7 @@ public class Result { @SerializedName("variations_map") private Object variationsMap; + // The value is returned in a list, but practically it would only be a single value list @SerializedName("variation_slice") private Map> variationSlice;