Skip to content

feat(lapis): also allow multiple value in int, float and date filters (and concatenate them with or)#1626

Open
fengelniederhammer wants to merge 6 commits intomainfrom
1595-search-for-int-and-float-fields-only-allows-exact-match
Open

feat(lapis): also allow multiple value in int, float and date filters (and concatenate them with or)#1626
fengelniederhammer wants to merge 6 commits intomainfrom
1595-search-for-int-and-float-fields-only-allows-exact-match

Conversation

@fengelniederhammer
Copy link
Copy Markdown
Contributor

@fengelniederhammer fengelniederhammer commented Mar 31, 2026

resolves #1595

int, float, and date exact-match filters now accept an array of values, combining them with logical OR — the same behaviour already supported for string fields.

{ "age": [50, 51] }
{ "qcValue": [0.95, 0.97] }
{ "date": ["2021-05-08", "2021-01-20"] }

null is supported as an array element to filter for missing values. Range filters (*From/*To) are unchanged and still accept a single value only.

PR Checklist

  • All necessary documentation has been adapted.
  • All necessary changes are explained in the llms.txt.
  • The implemented feature is covered by an appropriate test.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lapis Ready Ready Preview, Comment Apr 1, 2026 9:33am

Request Review

@fengelniederhammer fengelniederhammer changed the title feat(LAPIS): also allow multiple value in int and float filters (and concatenate them with or) feat(lapis): also allow multiple value in int and float filters (and concatenate them with or) Mar 31, 2026
@fengelniederhammer fengelniederhammer changed the title feat(lapis): also allow multiple value in int and float filters (and concatenate them with or) feat(lapis): also allow multiple value in int, float and date filters (and concatenate them with or) Apr 1, 2026
Copy link
Copy Markdown
Contributor

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

Adds multi-value exact-match support (logical OR semantics) for int, float, and date metadata filters in LAPIS—bringing them in line with existing multi-value behavior for string filters—and updates docs/tests accordingly.

Changes:

  • Extend int/float/date exact-match filters to accept multiple values and map them to an Or(...) SILO filter expression (including null as “is missing”).
  • Update OpenAPI + template/docs + docs-site filter descriptions to reflect new multi-value capability.
  • Add/adjust unit + e2e coverage for multi-value exact-match queries.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
lapis/src/main/kotlin/org/genspectrum/lapis/model/SiloFilterExpressionMapper.kt Implements OR-combination for multi-value exact-match int/float/date filters (including null).
lapis/src/main/kotlin/org/genspectrum/lapis/openApi/OpenApiDocs.kt Updates filter schemas so int/float/date exact-match filters accept either a scalar or an array.
lapis/src/main/resources/templates/llms.txt Updates end-user docs to describe array support for date/int/float exact matches.
lapis/src/test/kotlin/org/genspectrum/lapis/model/SiloFilterExpressionMapperTest.kt Adjusts/extends unit test expectations for OR-wrapped exact-match expressions and new multi-value cases.
lapis-e2e/test/aggregatedQueries/intEqualsMultiple.json New e2e aggregated-query fixture validating multi-value int equals behavior.
lapis-e2e/test/aggregatedQueries/floatEqualsMultiple.json New e2e aggregated-query fixture validating multi-value float equals behavior.
lapis-e2e/test/aggregatedQueries/dateEqualsMultiple.json New e2e aggregated-query fixture validating multi-value date equals behavior.
lapis-e2e/test/aminoAcidSequence.spec.ts Updates an assertion to match a changed SILO error message wording.
lapis-docs/src/components/FiltersTable/getFilters.tsx Updates docs-site filter descriptions to mention array/OR semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +41 to +43
description:
`Filters the "${metadata.name}" column with exact match. ` +
`You can also supply an array of values - they will be combined with logical OR.`,
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The filter docs generation for string fields still contains an extra double quote in column" with exact match, which results in a typo/inconsistent wording compared to the int/float/date descriptions. Remove the stray quote so the sentence reads correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +519 to +526
SequenceFilterFieldType.Int -> {
val fieldSchema = Schema<Int>().types(setOf(fieldType.openApiType))
Schema<Any>().anyOf(
listOf(
fieldSchema,
logicalOrArraySchema(fieldSchema),
),
)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The new OpenAPI schema allows int/float/date filters to be either a single value or an array, but it does not document that null is also accepted as an array element (and as a single value) to filter for missing values. Consider making the schema (and array item schema) nullable (or using an anyOf that includes null) so the OpenAPI contract matches the implemented behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +35
[# th:if="${dateField != null}"]- **Date fields**: Use exact match, or `From`/`To` suffixes for ranges. You can also supply an array for exact match - the values will be combined with logical OR.
Examples: `"[(${dateField})]": "2023-01-15"`, `"[(${dateField})]From": "2023-01-01", "[(${dateField})]To": "2023-12-31"`, `"[(${dateField})]": ["2023-01-15", "2023-02-20"]`[/]
[# th:if="${intField != null}"]- **Integer fields**: Use exact match or `From`/`To` for ranges. You can also supply an array for exact match - the values will be combined with logical OR.
Examples: `"[(${intField})]": 42`, `"[(${intField})]From": 10, "[(${intField})]To": 50`, `"[(${intField})]": [42, 43]`[/]
[# th:if="${floatField != null}"]- **Float fields**: Use exact match or `From`/`To` for ranges. You can also supply an array for exact match - the values will be combined with logical OR.
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

This section documents array support for exact date/int/float matches, but it doesn’t mention that null can be included as an array element to match missing values (as described in the PR). Add a short note and/or an example including null (or explicitly point users to the existing .isNull filter syntax) to avoid conflicting guidance.

Suggested change
[# th:if="${dateField != null}"]- **Date fields**: Use exact match, or `From`/`To` suffixes for ranges. You can also supply an array for exact match - the values will be combined with logical OR.
Examples: `"[(${dateField})]": "2023-01-15"`, `"[(${dateField})]From": "2023-01-01", "[(${dateField})]To": "2023-12-31"`, `"[(${dateField})]": ["2023-01-15", "2023-02-20"]`[/]
[# th:if="${intField != null}"]- **Integer fields**: Use exact match or `From`/`To` for ranges. You can also supply an array for exact match - the values will be combined with logical OR.
Examples: `"[(${intField})]": 42`, `"[(${intField})]From": 10, "[(${intField})]To": 50`, `"[(${intField})]": [42, 43]`[/]
[# th:if="${floatField != null}"]- **Float fields**: Use exact match or `From`/`To` for ranges. You can also supply an array for exact match - the values will be combined with logical OR.
[# th:if="${dateField != null}"]- **Date fields**: Use exact match, or `From`/`To` suffixes for ranges. You can also supply an array for exact match - the values will be combined with logical OR, and may include `null` to match missing values.
Examples: `"[(${dateField})]": "2023-01-15"`, `"[(${dateField})]From": "2023-01-01", "[(${dateField})]To": "2023-12-31"`, `"[(${dateField})]": ["2023-01-15", "2023-02-20"]`[/]
[# th:if="${intField != null}"]- **Integer fields**: Use exact match or `From`/`To` for ranges. You can also supply an array for exact match - the values will be combined with logical OR, and may include `null` to match missing values.
Examples: `"[(${intField})]": 42`, `"[(${intField})]From": 10, "[(${intField})]To": 50`, `"[(${intField})]": [42, 43]`[/]
[# th:if="${floatField != null}"]- **Float fields**: Use exact match or `From`/`To` for ranges. You can also supply an array for exact match - the values will be combined with logical OR, and may include `null` to match missing values.

Copilot uses AI. Check for mistakes.
const errorResponse = await response.json();
expect(errorResponse.error.detail).to.match(
/Error from SILO: The table does not contain the SequenceColumn 'unknownGene'/
/Error from SILO: The table does not contain the field unknownGene/
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Unrelated to this PR, but SILO recently changed the error message in this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Search for Int and float fields only allows exact match

2 participants