Problem/Motivation

Search API condition groups are not preserved when Azure filter parameters are built.

When a query contains a nested OR condition group, QueryFilterBuilder::buildQueryFilters() currently merges nested filters into the parent filter list. Later, QueryParamBuilder joins the returned filters with and, which can change the intended logic.

For example, a query intended to filter by (bibcite_year eq 2024 or bibcite_year eq 2025) can be flattened into separate filters and combined as bibcite_year eq 2024 and bibcite_year eq 2025.

The same area also affects multi-value integer fields that are represented in Azure as collections. Those fields must be filtered using Azure's any(...) syntax instead of scalar equality.

Steps to reproduce

1. Configure a Search API Azure AI Search index.
2. Add a Search API query condition group using OR, with two or more conditions.
3. Execute the query and inspect the generated Azure $filter parameter.
4. For the integer collection case, configure a multi-value integer field that is stored in Azure as a collection and filter by one or more values.

Expected result:

Nested condition groups preserve their conjunctions in the generated Azure filter, for example (field_a eq 1 or field_a eq 2). Integer collection fields use field/any(...) syntax.

Actual result:

Nested condition group filters are flattened and can be combined with and. Integer collection fields can be filtered as scalar fields, which is not valid for Azure collection fields.

Proposed resolution

Refactor condition filter building into a dedicated helper method, preserve nested condition groups by joining them with their own conjunction, and wrap top-level OR groups in parentheses.

Add integer collection filter handling for the affected multi-value integer field.

Attached patch:
preserve-query-filter-groups-and-integer-collections.patch

Remaining tasks

1. Review the patch.
2. Generalise the integer collection detection so it does not rely on a specific field machine name.
3. Add test coverage for nested OR condition groups and integer collection filters.

User interface changes

None.

Introduced terminology

None.

API changes

None.

Data model changes

None.

Release notes snippet

N/A

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

kieran.cott created an issue. See original summary.

kieran.cott changed the visibility of the branch 3592233-query-filters-flatten to hidden.

kieran.cott changed the visibility of the branch 3592233-query-filters-flatten to active.

kieran.cott changed the visibility of the branch 3592233-query-filters-flatten to hidden.

kr3ian’s picture

Tested this patch and it works for me

kieran.cott’s picture

StatusFileSize
new6.91 KB

Further to resolution of https://www.drupal.org/node/3592230, some of this patch/MR is no longer required. However, the underlying issue of QueryParamBuilder flattening a nested OR condition group and combining with AND appears to persist.

MR32 is now updated and the patch rerolled.

jacobsaw’s picture

Assigned: Unassigned » jacobsaw
jacobsaw’s picture

Hi Kieran,

Thank you for creating the issue and proactively addressing the changes from the other MR!

I am going to test this either today or Monday and will move it forward if it looks good. I have a case with nested conditions in my set up I can test against.

jacobsaw’s picture

Status: Active » Needs review
jacobsaw’s picture

Hi Kieran,

Apologies for the delay, I had to prioritize other work last week and only had time to get to the other issue we collaborated on.

Overall, this looks great! My nested filters were preserved and well formatted.

I am looking into the following error for one of my date fields, the patch I was using before testing yours had the date field without single quotes surrounding it and that seems to be the change causing the error:

Invalid expression: A binary operator with incompatible types was detected. Found operand types 'Edm.DateTimeOffset' and 'Edm.String' for operator kind 'GreaterThanOrEqual'. Parameter name: $filter

jacobsaw’s picture

This was what was needed to get rid of that error: 'aais.date_time_offset' => sprintf("%s %s %s", $condition->getField(), $operator, $condition->getValue()),.

Going to do a bit more testing and some other minor changes. Hoping to have this wrapped up this week.

jacobsaw’s picture

Version: 1.0.0-rc2 » 1.0.0-rc3
Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.