Skip to content

Commit 7e43acd

Browse files
[ML] Hold ML filter items in sorted set (#31338)
Filter items should be unique. They should also be sorted to make them easier to read plus save sorting in the autodetect process.
1 parent 363ec05 commit 7e43acd

File tree

3 files changed

+27
-15
lines changed

3 files changed

+27
-15
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/config/MlFilter.java

+12-9
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
import org.elasticsearch.xpack.core.ml.MlMetaIndex;
1818

1919
import java.io.IOException;
20-
import java.util.ArrayList;
2120
import java.util.Arrays;
2221
import java.util.Collections;
2322
import java.util.List;
2423
import java.util.Objects;
24+
import java.util.SortedSet;
25+
import java.util.TreeSet;
2526

2627
public class MlFilter implements ToXContentObject, Writeable {
2728

@@ -53,9 +54,9 @@ private static ObjectParser<Builder, Void> createParser(boolean ignoreUnknownFie
5354

5455
private final String id;
5556
private final String description;
56-
private final List<String> items;
57+
private final SortedSet<String> items;
5758

58-
public MlFilter(String id, String description, List<String> items) {
59+
public MlFilter(String id, String description, SortedSet<String> items) {
5960
this.id = Objects.requireNonNull(id, ID.getPreferredName() + " must not be null");
6061
this.description = description;
6162
this.items = Objects.requireNonNull(items, ITEMS.getPreferredName() + " must not be null");
@@ -68,7 +69,8 @@ public MlFilter(StreamInput in) throws IOException {
6869
} else {
6970
description = null;
7071
}
71-
items = Arrays.asList(in.readStringArray());
72+
items = new TreeSet<>();
73+
items.addAll(Arrays.asList(in.readStringArray()));
7274
}
7375

7476
@Override
@@ -103,8 +105,8 @@ public String getDescription() {
103105
return description;
104106
}
105107

106-
public List<String> getItems() {
107-
return new ArrayList<>(items);
108+
public SortedSet<String> getItems() {
109+
return Collections.unmodifiableSortedSet(items);
108110
}
109111

110112
@Override
@@ -142,7 +144,7 @@ public static class Builder {
142144

143145
private String id;
144146
private String description;
145-
private List<String> items = Collections.emptyList();
147+
private SortedSet<String> items = new TreeSet<>();
146148

147149
private Builder() {}
148150

@@ -162,12 +164,13 @@ public Builder setDescription(String description) {
162164
}
163165

164166
public Builder setItems(List<String> items) {
165-
this.items = items;
167+
this.items = new TreeSet<>();
168+
this.items.addAll(items);
166169
return this;
167170
}
168171

169172
public Builder setItems(String... items) {
170-
this.items = Arrays.asList(items);
173+
setItems(Arrays.asList(items));
171174
return this;
172175
}
173176

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/job/config/MlFilterTests.java

+14-5
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111
import org.elasticsearch.test.AbstractSerializingTestCase;
1212

1313
import java.io.IOException;
14-
import java.util.ArrayList;
15-
import java.util.Collections;
16-
import java.util.List;
14+
import java.util.TreeSet;
1715

16+
import static org.hamcrest.Matchers.contains;
1817
import static org.hamcrest.Matchers.containsString;
1918
import static org.hamcrest.Matchers.equalTo;
2019

@@ -40,7 +39,7 @@ public static MlFilter createRandom(String filterId) {
4039
}
4140

4241
int size = randomInt(10);
43-
List<String> items = new ArrayList<>(size);
42+
TreeSet<String> items = new TreeSet<>();
4443
for (int i = 0; i < size; i++) {
4544
items.add(randomAlphaOfLengthBetween(1, 20));
4645
}
@@ -58,7 +57,7 @@ protected MlFilter doParseInstance(XContentParser parser) {
5857
}
5958

6059
public void testNullId() {
61-
NullPointerException ex = expectThrows(NullPointerException.class, () -> new MlFilter(null, "", Collections.emptyList()));
60+
NullPointerException ex = expectThrows(NullPointerException.class, () -> new MlFilter(null, "", new TreeSet<>()));
6261
assertEquals(MlFilter.ID.getPreferredName() + " must not be null", ex.getMessage());
6362
}
6463

@@ -88,4 +87,14 @@ public void testLenientParser() throws IOException {
8887
MlFilter.LENIENT_PARSER.apply(parser, null);
8988
}
9089
}
90+
91+
public void testItemsAreSorted() {
92+
MlFilter filter = MlFilter.builder("foo").setItems("c", "b", "a").build();
93+
assertThat(filter.getItems(), contains("a", "b", "c"));
94+
}
95+
96+
public void testGetItemsReturnsUnmodifiable() {
97+
MlFilter filter = MlFilter.builder("foo").setItems("c", "b", "a").build();
98+
expectThrows(UnsupportedOperationException.class, () -> filter.getItems().add("x"));
99+
}
91100
}

x-pack/plugin/src/test/resources/rest-api-spec/test/ml/filter_crud.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ setup:
2222
filter_id: filter-foo
2323
body: >
2424
{
25-
"items": ["abc", "xyz"]
25+
"items": ["xyz", "abc"]
2626
}
2727
2828
- do:

0 commit comments

Comments
 (0)