Skip to content

Commit

Permalink
Labels multiselect: (#7544)
Browse files Browse the repository at this point in the history
combine the labels filter by operation to handle multiselect when building the query
  • Loading branch information
aeSouid authored Feb 25, 2025
1 parent be04c16 commit 2bb5ac6
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ protected void find() {
executions = executionRepository.find(Pageable.from(1, 10), null, filters);
assertThat(executions.getTotal(), is(0L));

filters = List.of(QueryFilter.builder()
.field(QueryFilter.Field.LABELS)
.operation(QueryFilter.Op.EQUALS)
.value(Map.of("key", "value", "keyTest", "valueTest"))
.build()
);
executions = executionRepository.find(Pageable.from(1, 10), null, filters);
assertThat(executions.getTotal(), is(1L));

filters = List.of(QueryFilter.builder()
.field(QueryFilter.Field.FLOW_ID)
.operation(QueryFilter.Op.EQUALS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ public static Condition findCondition(Map<?, ?> labels, QueryFilter.Op operation
});


return conditions.isEmpty() ? DSL.trueCondition() : DSL.and(conditions);
return conditions.isEmpty() ? DSL.trueCondition() : DSL.or(conditions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ public static Condition findCondition(Object labels, QueryFilter.Op operation) {
});

}
return conditions.isEmpty() ? DSL.trueCondition() : DSL.and(conditions);
return conditions.isEmpty() ? DSL.trueCondition() : DSL.or(conditions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static Condition findCondition(Map<?,?> labels, QueryFilter.Op operation)

});

return conditions.isEmpty() ? DSL.trueCondition() : DSL.and(conditions);
return conditions.isEmpty() ? DSL.trueCondition() : DSL.or(conditions);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ public static Condition findCondition(Object labels, QueryFilter.Op operation) {

});
}
return conditions.isEmpty() ? DSL.trueCondition() : DSL.and(conditions);
return conditions.isEmpty() ? DSL.trueCondition() : DSL.or(conditions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static Condition findCondition(Map<?,?> labels, QueryFilter.Op operation)

});

return conditions.isEmpty() ? DSL.trueCondition() : DSL.and(conditions);
return conditions.isEmpty() ? DSL.trueCondition() : DSL.or(conditions);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ public static Condition findCondition(Object labels, QueryFilter.Op operation) {
if (labels instanceof Map<?, ?> labelValues) {
labelValues.forEach((key, value) -> {
String sql = "value -> 'labels' @> '[{\"key\":\"" + key + "\", \"value\":\"" + value + "\"}]'";
if (operation.equals(EQUALS))
if (operation.equals(EQUALS)) {
conditions.add(DSL.condition(sql));
else
} else {
conditions.add(DSL.not(DSL.condition(sql)));

}
});
}
return conditions.isEmpty() ? DSL.trueCondition() : DSL.and(conditions);
return conditions.isEmpty() ? DSL.trueCondition() : DSL.or(conditions);
}


Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/filter/KestraFilter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@
};
// Check if parent filter already exists
const existingFilterIndex = currentFilters.value.findIndex(
const existingFilterIndex = currentFilters.value.filter((itm) => itm.label !== "labels").findIndex(
(item) => item.label === option.value.label,
);
if (existingFilterIndex !== -1) {
Expand Down Expand Up @@ -395,7 +395,7 @@
const isOptionDisabled = () => {
if (!activeParentFilter.value) return false;
const parentIndex = currentFilters.value.findIndex(
const parentIndex = currentFilters.value.filter((itm) => itm.label !== "labels").findIndex(
(item) => item.label === activeParentFilter.value,
);
if (parentIndex === -1) return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -25,14 +26,25 @@ public class QueryFilterFormatBinder implements AnnotatedRequestArgumentBinder<Q
@VisibleForTesting
static List<QueryFilter> getQueryFilters(Map<String, List<String>> queryParams) {
List<QueryFilter> filters = new ArrayList<>();
Map<QueryFilter.Op, Map<String, String>> labelsByOperation = new HashMap<>(); // Group labels by operation

queryParams.forEach((key, values) -> {
if (!key.startsWith("filters[")) return;

Matcher matcher = FILTER_PATTERN.matcher(key);

if (matcher.matches()) {
parseFilters(values, matcher, filters);
parseFilters(values, matcher, filters, labelsByOperation);
}
});
// Add a QueryFilter for each operation's labels
labelsByOperation.forEach((operation, labels) -> {
if (!labels.isEmpty()) {
filters.add(QueryFilter.builder()
.field(QueryFilter.Field.LABELS)
.operation(operation)
.value(labels)
.build());
}
});

Expand All @@ -53,21 +65,25 @@ public BindingResult<List<QueryFilter>> bind(ArgumentConversionContext<List<Quer
return () -> Optional.of(filters);
}

private static void parseFilters(List<String> values, Matcher matcher, List<QueryFilter> filters) {
private static void parseFilters(List<String> values, Matcher matcher, List<QueryFilter> filters, Map<QueryFilter.Op, Map<String, String>> labelsByOperation) {
String fieldStr = matcher.group(1);
String operationStr = matcher.group(2);
String nestedKey = matcher.group(3); // Extract nested key if present
String nestedKey = matcher.group(3); // Extract nested key if present

QueryFilter.Field field = QueryFilter.Field.fromString(fieldStr);
QueryFilter.Op operation = QueryFilter.Op.fromString(operationStr);

Object value = nestedKey != null ? Map.of(nestedKey, values.getFirst()) : getFlatValue(values, field, operation);

filters.add(QueryFilter.builder()
.field(field)
.operation(operation)
.value(value)
.build());
// For labels: Add the key-value to the appropriate operation's map
if (field == QueryFilter.Field.LABELS && nestedKey != null) {
labelsByOperation.computeIfAbsent(operation, k -> new HashMap<>()).put(nestedKey, values.getFirst());
} else {
Object value = nestedKey != null ? Map.of(nestedKey, values.getFirst()) : getFlatValue(values, field, operation);
filters.add(QueryFilter.builder()
.field(field)
.operation(operation)
.value(value)
.build());
}
}

private static Object getFlatValue(List<String> values, QueryFilter.Field field, QueryFilter.Op operation) {
Expand Down

0 comments on commit 2bb5ac6

Please sign in to comment.