[SABRA-2456] Add V2 Facets and Searchabilities API Support#179
[SABRA-2456] Add V2 Facets and Searchabilities API Support#179aandrukhovich wants to merge 3 commits intomasterfrom
Conversation
This comment has been minimized.
This comment has been minimized.
Code Review SummaryThis PR adds well-structured support for the v2 Facets and Searchabilities APIs. The implementation follows existing project conventions (Gson, Detailed Feedback[Bug: The single-facet and list-facets GET methods correctly use if (offset != null && offset > 0 && page == null) {An if (offset != null && offset >= 0 && page == null) {[Bug:
[Bug:
urlBuilder.addQueryParameter("section",
(section != null && !section.trim().isEmpty()) ? section : DEFAULT_SECTION);But urlBuilder.addQueryParameter("section", facetConfigurationV2Request.getSection())Since [Issue: All other v2 methods accept a dedicated request object (e.g., [Issue: Throughout the new methods, String params = new Gson().toJson(facetConfigurationV2Request.getFacetConfiguration());This is the same pattern used in the existing v1 code, so it's not a regression, but it is wasteful. Each [Issue: The v1 [Issue: The v1 [Issue: The public SearchabilityV2Request(String name, String section) {
this(null, name, section);
}This is intentional for GET/DELETE operations, but if (searchabilityV2Request.getSearchability() == null) {
throw new IllegalArgumentException("searchability body is required for create/update operations");
}[Issue: In integration tests like // After: String response = constructor.createFacetConfigurationV2(request);
addFacetToCleanupArray(facetName); // register cleanup BEFORE asserting
assertNotNull(response);
// ...[Issue: private static String apiKey = System.getenv("TEST_CATALOG_FACETS_V2_API_KEY");Both [Issue: assertEquals(true, jsonObj.get("fuzzy_searchable"));
assertEquals(false, jsonObj.get("exact_searchable"));These values are duplicated from [Minor: All getters in [Minor: public SearchabilitiesV2GetRequest(String section) {
if (section == null) {
throw new IllegalArgumentException("section is required");
}
this.section = section;
}
ConclusionThe PR is a solid foundation for the v2 API surface. The overall structure, documentation, and test coverage are good. The two items that need fixing before merge are the |
There was a problem hiding this comment.
Pull request overview
Adds Java client support for Constructor.io v2 Facets and v2 Searchabilities APIs, introducing new models/request objects plus ConstructorIO methods and accompanying unit/integration tests.
Changes:
- Added v2 model + request classes for facet configurations and searchabilities (single/bulk, plus GET filtering/pagination and bulk delete).
- Implemented v2 endpoints in
ConstructorIOfor facets and searchabilities CRUD/bulk operations. - Added test fixtures, unit tests, integration tests, and CI env wiring for the new v2 API key.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| constructorio-client/src/test/resources/searchability.v2.json | Test fixture JSON for v2 searchability serialization/deserialization. |
| constructorio-client/src/test/resources/facet.configuration.v2.json | Test fixture JSON for v2 facet configuration (includes path_in_metadata). |
| constructorio-client/src/test/java/io/constructor/client/SearchabilityV2Test.java | Unit tests for SearchabilityV2 model + v2 request objects. |
| constructorio-client/src/test/java/io/constructor/client/FacetConfigurationV2Test.java | Unit tests for FacetConfigurationV2 model + v2 request objects. |
| constructorio-client/src/test/java/io/constructor/client/ConstructorIOSearchabilityV2Test.java | Integration tests covering v2 searchabilities endpoints. |
| constructorio-client/src/test/java/io/constructor/client/ConstructorIOFacetConfigurationV2Test.java | Integration tests covering v2 facets endpoints. |
| constructorio-client/src/main/java/io/constructor/client/models/SearchabilityV2.java | New v2 searchability model (Gson-mapped fields). |
| constructorio-client/src/main/java/io/constructor/client/models/FacetConfigurationV2.java | New v2 facet configuration model (adds path_in_metadata and range fields). |
| constructorio-client/src/main/java/io/constructor/client/SearchabilityV2Request.java | New request type for single searchability v2 operations (incl. skip_rebuild). |
| constructorio-client/src/main/java/io/constructor/client/SearchabilitiesV2Request.java | New request type for bulk searchabilities v2 PATCH operations. |
| constructorio-client/src/main/java/io/constructor/client/SearchabilitiesV2GetRequest.java | New request type for v2 searchabilities listing (filters + pagination). |
| constructorio-client/src/main/java/io/constructor/client/SearchabilitiesV2DeleteRequest.java | New request type for v2 bulk searchability deletion. |
| constructorio-client/src/main/java/io/constructor/client/FacetConfigurationsV2Request.java | New request type for v2 bulk facet update/replace operations. |
| constructorio-client/src/main/java/io/constructor/client/FacetConfigurationV2Request.java | New request type for single facet v2 create/update/replace/delete operations. |
| constructorio-client/src/main/java/io/constructor/client/ConstructorIO.java | Added v2 Facets/Searchabilities API methods and introduced DEFAULT_SECTION. |
| .github/workflows/run-tests.yml | Added TEST_CATALOG_FACETS_V2_API_KEY env var for CI. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| HttpUrl url = urlBuilder.build(); | ||
|
|
||
| String params = new Gson().toJson(searchabilityV2Request.getSearchability()); | ||
| RequestBody body = | ||
| RequestBody.create(params, MediaType.parse("application/json; charset=utf-8")); |
There was a problem hiding this comment.
createOrUpdateSearchabilityV2 serializes searchabilityV2Request.getSearchability() without validating it is non-null. Because SearchabilityV2Request is also used for GET/DELETE (and those constructors set searchability to null), passing the wrong request type here will send a literal null JSON body and likely fail at runtime. Add a guard that getSearchability() is non-null (and ideally that its name matches the path name) and throw IllegalArgumentException if invalid.
Summary
This PR adds support for the v2 versions of the facets and searchabilities APIs, which include additional fields and capabilities not available in v1.
Key Changes
New Model Classes:
FacetConfigurationV2- v2 facet configuration withpath_in_metadatafield supportSearchabilityV2- Searchability configuration modelNew Request Classes:
FacetConfigurationV2Request- Single facet v2 operationsFacetConfigurationsV2Request- Bulk facet v2 operationsSearchabilityV2Request- Single searchability operationsSearchabilitiesV2Request- Bulk searchability PATCH operationsSearchabilitiesV2GetRequest- Searchability list operations with filtering/paginationSearchabilitiesV2DeleteRequest- Bulk searchability deletionNew API Methods in
ConstructorIO:GET /v2/facetsretrieveFacetConfigurationsV2()GET /v2/facets/{name}retrieveFacetConfigurationV2()POST /v2/facetscreateFacetConfigurationV2()PUT /v2/facets/{name}replaceFacetConfigurationV2()PATCH /v2/facets/{name}updateFacetConfigurationV2()PATCH /v2/facetsupdateFacetConfigurationsV2()PUT /v2/facetsreplaceFacetConfigurationsV2()DELETE /v2/facets/{name}deleteFacetConfigurationV2()GET /v2/searchabilitiesretrieveSearchabilitiesV2()GET /v2/searchabilities/{name}retrieveSearchabilityV2()PATCH /v2/searchabilities/{name}createOrUpdateSearchabilityV2()PATCH /v2/searchabilitiescreateOrUpdateSearchabilitiesV2()DELETE /v2/searchabilities/{name}deleteSearchabilityV2()DELETE /v2/searchabilitiesdeleteSearchabilitiesV2()v2 API Differences from v1
path_in_metadatafield which specifies where in item metadata the facet data is locatedskip_rebuildparameterTest Plan