feat(search): push AttributeFilter list into ClickHouse WHERE clause

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-24 10:13:30 +02:00
parent f9b5f235cc
commit 2dcbd5a772
2 changed files with 76 additions and 2 deletions

View File

@@ -2,6 +2,7 @@ package com.cameleer.server.app.search;
import com.cameleer.server.app.storage.ClickHouseExecutionStore;
import com.cameleer.server.core.ingestion.MergedExecution;
import com.cameleer.server.core.search.AttributeFilter;
import com.cameleer.server.core.search.ExecutionSummary;
import com.cameleer.server.core.search.SearchRequest;
import com.cameleer.server.core.search.SearchResult;
@@ -62,7 +63,7 @@ class ClickHouseSearchIndexIT {
500L,
"", "", "", "", "", "",
"hash-abc", "FULL",
"{\"order\":\"12345\"}", "", "", "", "", "", "{\"env\":\"prod\"}",
"", "", "", "", "", "", "{\"order\":\"12345\",\"tenant\":\"acme\"}",
"", "",
false, false,
null, null
@@ -79,7 +80,7 @@ class ClickHouseSearchIndexIT {
"java.lang.NPE\n at Foo.bar(Foo.java:42)",
"NullPointerException", "RUNTIME", "", "",
"", "FULL",
"", "", "", "", "", "", "",
"", "", "", "", "", "", "{\"order\":\"99999\"}",
"", "",
false, false,
null, null
@@ -309,4 +310,59 @@ class ClickHouseSearchIndexIT {
assertThat(result.total()).isEqualTo(1);
assertThat(result.data().get(0).executionId()).isEqualTo("exec-1");
}
@Test
void search_byAttributeFilter_exactMatch_matchesExec1() {
SearchRequest request = new SearchRequest(
null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, 0, 50, null, null, null, null,
List.of(new AttributeFilter("order", "12345")));
SearchResult<ExecutionSummary> result = searchIndex.search(request);
assertThat(result.total()).isEqualTo(1);
assertThat(result.data().get(0).executionId()).isEqualTo("exec-1");
}
@Test
void search_byAttributeFilter_keyOnly_matchesExec1AndExec2() {
SearchRequest request = new SearchRequest(
null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, 0, 50, null, null, null, null,
List.of(new AttributeFilter("order", null)));
SearchResult<ExecutionSummary> result = searchIndex.search(request);
assertThat(result.total()).isEqualTo(2);
assertThat(result.data()).extracting(ExecutionSummary::executionId)
.containsExactlyInAnyOrder("exec-1", "exec-2");
}
@Test
void search_byAttributeFilter_wildcardValue_matchesExec1Only() {
SearchRequest request = new SearchRequest(
null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, 0, 50, null, null, null, null,
List.of(new AttributeFilter("order", "123*")));
SearchResult<ExecutionSummary> result = searchIndex.search(request);
assertThat(result.total()).isEqualTo(1);
assertThat(result.data().get(0).executionId()).isEqualTo("exec-1");
}
@Test
void search_byAttributeFilter_multipleFiltersAreAnded() {
SearchRequest request = new SearchRequest(
null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, 0, 50, null, null, null, null,
List.of(
new AttributeFilter("order", "12345"),
new AttributeFilter("tenant", "acme")));
SearchResult<ExecutionSummary> result = searchIndex.search(request);
assertThat(result.total()).isEqualTo(1);
assertThat(result.data().get(0).executionId()).isEqualTo("exec-1");
}
}