[ML] Influencers come after analysis fields (elastic/x-pack-elasticsearch#646)

Original commit: elastic/x-pack-elasticsearch@f37835b140
This commit is contained in:
David Kyle 2017-02-24 15:12:35 +00:00 committed by GitHub
parent 8ecdf3b288
commit 8a3706f395
2 changed files with 34 additions and 7 deletions

View File

@ -23,11 +23,10 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
/** /**
* Anomaly Record POJO. * Anomaly Record POJO.
@ -296,7 +295,7 @@ public class AnomalyRecord extends ToXContentToBytes implements Writeable {
builder.field(INFLUENCERS.getPreferredName(), influences); builder.field(INFLUENCERS.getPreferredName(), influences);
} }
Map<String, Set<String>> inputFields = inputFieldMap(); Map<String, LinkedHashSet<String>> inputFields = inputFieldMap();
for (String fieldName : inputFields.keySet()) { for (String fieldName : inputFields.keySet()) {
builder.field(fieldName, inputFields.get(fieldName)); builder.field(fieldName, inputFields.get(fieldName));
} }
@ -305,8 +304,9 @@ public class AnomalyRecord extends ToXContentToBytes implements Writeable {
return builder; return builder;
} }
private Map<String, Set<String>> inputFieldMap() { private Map<String, LinkedHashSet<String>> inputFieldMap() {
Map<String, Set<String>> result = new HashMap<>(); // LinkedHashSet preserves insertion order when iterating entries
Map<String, LinkedHashSet<String>> result = new HashMap<>();
addInputFieldsToMap(result, byFieldName, byFieldValue); addInputFieldsToMap(result, byFieldName, byFieldValue);
addInputFieldsToMap(result, overFieldName, overFieldValue); addInputFieldsToMap(result, overFieldName, overFieldValue);
@ -323,10 +323,10 @@ public class AnomalyRecord extends ToXContentToBytes implements Writeable {
return result; return result;
} }
private void addInputFieldsToMap(Map<String, Set<String>> inputFields, String fieldName, String fieldValue) { private void addInputFieldsToMap(Map<String, LinkedHashSet<String>> inputFields, String fieldName, String fieldValue) {
if (!Strings.isNullOrEmpty(fieldName) && fieldValue != null) { if (!Strings.isNullOrEmpty(fieldName) && fieldValue != null) {
if (ReservedFieldNames.isValidFieldName(fieldName)) { if (ReservedFieldNames.isValidFieldName(fieldName)) {
inputFields.computeIfAbsent(fieldName, k -> new HashSet<String>()).add(fieldValue); inputFields.computeIfAbsent(fieldName, k -> new LinkedHashSet<>()).add(fieldValue);
} }
} }
} }

View File

@ -115,6 +115,33 @@ public class AnomalyRecordTests extends AbstractSerializingTestCase<AnomalyRecor
assertEquals(influence2.getInfluencerFieldValues(), serialisedInfFieldValues2); assertEquals(influence2.getInfluencerFieldValues(), serialisedInfFieldValues2);
} }
public void testToXContentOrdersDuplicateInputFields() throws IOException {
AnomalyRecord record = createTestInstance();
record.setByFieldName("car-make");
record.setByFieldValue("ford");
record.setOverFieldName("number-of-wheels");
record.setOverFieldValue("4");
record.setPartitionFieldName("spoiler");
record.setPartitionFieldValue("yes");
Influence influence1 = new Influence("car-make", Collections.singletonList("VW"));
Influence influence2 = new Influence("number-of-wheels", Collections.singletonList("18"));
Influence influence3 = new Influence("spoiler", Collections.singletonList("no"));
record.setInfluencers(Arrays.asList(influence1, influence2, influence3));
// influencer fields with the same name as a by/over/partitiion field
// come second in the list
XContentBuilder builder = toXContent(record, XContentType.JSON);
XContentParser parser = createParser(builder);
Map<String, Object> map = parser.map();
List<String> serialisedCarMakeFieldValues = (List<String>) map.get("car-make");
assertEquals(Arrays.asList("ford", "VW"), serialisedCarMakeFieldValues);
List<String> serialisedNumberOfWheelsFieldValues = (List<String>) map.get("number-of-wheels");
assertEquals(Arrays.asList("4", "18"), serialisedNumberOfWheelsFieldValues);
List<String> serialisedSpoilerFieldValues = (List<String>) map.get("spoiler");
assertEquals(Arrays.asList("yes", "no"), serialisedSpoilerFieldValues);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void testToXContentDoesNotIncludesReservedWordInputFields() throws IOException { public void testToXContentDoesNotIncludesReservedWordInputFields() throws IOException {
AnomalyRecord record = createTestInstance(); AnomalyRecord record = createTestInstance();