Skip to content

Add backwards-compatible serialization for filtration #840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Noah-Mack-01
Copy link

@Noah-Mack-01 Noah-Mack-01 commented Apr 19, 2025

Pull Request - Add new FiltrationAttributes POJO and update implementation of Settings, Index.

Related issue

Fixes #838

What does this PR do?

New Additions

  • FilterableAttribute is a flattened POJO implementation of the new granular filtration feature. It contains backwards compatibility with legacy data.
  • GsonFilterableAttributeSerializer allows for the serialization/deserialization of these POJOs from legacy primitive string filter attributes, as well as the persistence of new single-string attributes with default settings in legacy format.

Changes

  • GsonJsonHandler registers our new serializer.
  • Index: getFilterableAttributesSettings is updated to accommodate the new POJO. Backwards compatible legacyGetFilterableAttributesSettings which returns the traditional String[] attribute configuration has been added as well. updateFilterableAttributes has been updated to accept Object[], as polymorphic backwards compatibility which can accept null values, requires no ambiguity; as we cannot do a polymorphic method, this seemed the best fit.
  • Settings: filterableAttributes was updated to now be of type FilterableAttribute[].
  • SettingsHandler: updateFilterableAttributesSettings now accepts a FilterableAttribute[] object. getFilterableAttributesSettings now returns one likewise.

PR checklist

Please check if your PR fulfills the following requirements:

  • Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
  • Have you read the contributing guidelines?
  • Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!

### New Additions
* **`FilterableAttribute`** is a flattened POJO implementation
   of the new [granular filtration feature](meilisearch/meilisearch#5163).
   It contains backwards compatibility with legacy data.
* **`GsonFilterableAttributeSerializer`** allows for the
   serialization/deserialization of these POJOs from legacy
   primitive string filter attributes, as well as the persistence
   of new single-string attributes with default settings in
   legacy format.
### Changes
* **`GsonJsonHandler`** registers our new serializer.
* **`Index`**: `getFilterableAttributesSettings` is updated
   to accommodate the new POJO. Backwards compatible
   `legacyGetFilterableAttributesSettings` which returns
   the traditional `String[]` attribute configuration has been
   added as well. `updateFilterableAttributes` has been
   updated to accept `Object[]`, as polymorphic backwards
   compatibility which can accept `null` values, requires no
   ambiguity; as we cannot do a polymorphic method, this
   seemed the best fit.
* **`Settings`**: `filterableAttributes` was updated to now
  be of type `FilterableAttribute[]`.
* **`SettingsHandler`**: `updateFilterableAttributesSettings`
  now accepts a `FilterableAttribute[]` object.
  `getFilterableAttributesSettings` now returns one likewise.
@Strift Strift requested a review from Copilot April 21, 2025 06:10
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a new FilterableAttribute POJO along with a backwards-compatible Gson serializer/deserializer and updates to Settings and Index to support the new filtration format while preserving legacy functionality. Key changes include:

  • Adding new serialization/deserialization logic for FilterableAttribute in GsonFilterableAttributeSerializer and its tests.
  • Updating Settings and Index classes to handle FilterableAttribute arrays and provide legacy support.
  • Modifying integration tests and code samples to work with the new filtration attributes.

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/test/java/com/meilisearch/sdk/json/GsonFilterableAttributeSerializerTest.java Unit tests for verifying legacy and new serialization behaviors.
src/test/java/com/meilisearch/integration/TasksTest.java Integration tests now print debug information for task queries.
src/test/java/com/meilisearch/integration/SettingsTest.java Tests updated to use legacy methods and new methods for filterable attributes settings.
src/test/java/com/meilisearch/integration/FilterableAttributeTest.java Unit tests for the FilterableAttribute POJO constructors and validations.
src/main/java/com/meilisearch/sdk/model/Settings.java Updated settings to use FilterableAttribute[] and added a helper to convert legacy strings.
src/main/java/com/meilisearch/sdk/model/FilterableAttribute.java New POJO implementation for filtration settings with validation for geo patterns.
src/main/java/com/meilisearch/sdk/json/GsonJsonHandler.java Registers the new serializer for FilterableAttribute.
src/main/java/com/meilisearch/sdk/json/GsonFilterableAttributeSerializer.java Implements Gson serialization and deserialization for FilterableAttribute.
src/main/java/com/meilisearch/sdk/SettingsHandler.java Modified to support FilterableAttribute in get/update/reset settings.
src/main/java/com/meilisearch/sdk/Index.java Updated to provide both legacy and new methods for filterable attributes settings.
.code-samples.meilisearch.yaml Updated samples to demonstrate the new filterable attributes setup.
Comments suppressed due to low confidence (3)

.code-samples.meilisearch.yaml:233

  • There is an inconsistency with class and variable names – use 'FilterableAttribute' instead of 'FilterableAttributes' and ensure that the correct variable (e.g., 'filtersTypes') is passed in the constructor.
settings.setFilterableAttributes(new FilterableAttributes[] {new FilterableAttributes("genres"), new FilterableAttributes(new String[]{"director"}, true, filters)});

src/test/java/com/meilisearch/sdk/json/GsonFilterableAttributeSerializerTest.java:98

  • The testDoubleEncoding: 'array' already holds the encoded string value, so re-encoding it may lead to incorrect output. Compare 'array' directly with expectedOutput to ensure correct behavior.
assertEquals(expectedOutput, handler.encode(array));

src/test/java/com/meilisearch/integration/TasksTest.java:145

  • [nitpick] Remove the debugging print statements; they are likely leftover from development and are not needed in committed integration tests.
System.out.println("Expected from: " + from);

@Noah-Mack-01
Copy link
Author

@Strift PR in relation to #838

LMK if you have any questions or concerns!

@Strift Strift requested review from curquiza and brunoocasali April 22, 2025 01:58
@curquiza curquiza added the enhancement New feature or request label Apr 22, 2025
@curquiza
Copy link
Member

Hello!

Thank you for your PR @Noah-Mack-01! ❤️

If I understand correctly, this PR introduces breaking changes, because people need to use the legacy methods to have the same behavior than before.
It's ok to make breaking changes, we are not stable yet in this library, but we need to know which ones to do the appropriate changelogs

Also, is there a way to avoid breaking change? Make the new methods to accept both of format (array of string and array of object)?

I would love having the review of @brunoocasali before merging that

@Noah-Mack-01
Copy link
Author

Noah-Mack-01 commented Apr 23, 2025

Hi @curquiza !!

Thinking through this now. Its unfortunate we're working off such an old JDK, since Java 15's sealed interface would be useful in this situation. There's only one method that's been migrated to a legacy tag, and thats a getter method to retrieve the older String[] format of filters.

All update methods are generic, such as the following:

public <O> TaskInfo updateFilterableAttributesSettings(O[] filterableAttributes)
            throws MeilisearchException {
        if (filterableAttributes == null)
            return this.settingsHandler.updateFilterableAttributesSettings(this.uid, null);
        else if (filterableAttributes.getClass().getComponentType() == FilterableAttribute.class)
            return this.settingsHandler.updateFilterableAttributesSettings(
                    this.uid, (FilterableAttribute[]) filterableAttributes);
        else if (filterableAttributes.getClass().getComponentType() == String.class)
            return this.updateFilterableAttributeSettingsLegacy((String[]) filterableAttributes);
        else
            throw new MeilisearchException(
                    "filterableAttributes must be of type String or FilterableAttribute");
    }
    private TaskInfo updateFilterableAttributeSettingsLegacy(String[] filterableAttributes) {
        return this.settingsHandler.updateFilterableAttributesSettings(
                this.uid,
                Arrays.stream(filterableAttributes)
                        .map(FilterableAttribute::new)
                        .toArray(FilterableAttribute[]::new));
    }

However I can't think of a way to guarantee that the getFilterableAttributesSettings() method will return EITHER a String[] or FilterableAttribute[], and we can't utilize polymorphism here since there aren't parameters to the method.

I suppose the answer would be to maintain the legacy implementation's original nomenclature getFilterableAttributeSettings and refer to the new method's implementation as something else. Let me know what you think!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[v1.14] Filterable attributes settings opt-out
3 participants