Skip to content

Commit

Permalink
Core: Fix script fields to be returned as a multivalued field when th…
Browse files Browse the repository at this point in the history
…ey produce a list.

This change is essentially the same as #3015 but on script fields.

Close #8592
  • Loading branch information
jpountz committed Nov 24, 2014
1 parent bc52ccf commit 8346e92
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
32 changes: 32 additions & 0 deletions docs/reference/migration/migrate_2_0.asciidoc
Expand Up @@ -56,3 +56,35 @@ The `memory` / `ram` store (`index.store.type`) option was removed in Elasticsea
=== Term Vectors API

Usage of `/_termvector` is deprecated, and replaced in favor of `/_termvectors`.

=== Script fields

Script fields in 1.x were only returned as a single value. So even if the return
value of a script used to be list, it would be returned as an array containing
a single value that is a list too, such as:

[source,json]
---------------
"fields": {
"my_field": [
[
"v1",
"v2"
]
]
}
---------------

In elasticsearch 2.x, scripts that return a list of values are considered as
multivalued fields. So the same example would return the following response,
with values in a single array.

[source,json]
---------------
"fields": {
"my_field": [
"v1",
"v2"
]
}
---------------
Expand Up @@ -19,6 +19,7 @@
package org.elasticsearch.search.fetch.script;

import com.google.common.collect.ImmutableMap;

import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.search.SearchHitField;
Expand All @@ -29,7 +30,10 @@
import org.elasticsearch.search.internal.SearchContext;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
Expand Down Expand Up @@ -86,10 +90,17 @@ public void hitExecute(SearchContext context, HitContext hitContext) throws Elas

SearchHitField hitField = hitContext.hit().fields().get(scriptField.name());
if (hitField == null) {
hitField = new InternalSearchHitField(scriptField.name(), new ArrayList<>(2));
final List<Object> values;
if (value == null) {
values = Collections.emptyList();
} else if (value instanceof Collection) {
values = new ArrayList<>((Collection<?>) value);
} else {
values = Collections.singletonList(value);
}
hitField = new InternalSearchHitField(scriptField.name(), values);
hitContext.hit().fields().put(scriptField.name(), hitField);
}
hitField.values().add(value);
}
}
}
Expand Up @@ -385,7 +385,7 @@ private void checkArrayValsInEachDoc(String script, HashMap<String, List<Object>
assertHitCount(sr, expectedHitSize);
int nullCounter = 0;
for (SearchHit hit : sr.getHits().getHits()) {
Object result = hit.getFields().get("tvtest").getValues().get(0);
Object result = hit.getFields().get("tvtest").getValues();
Object expectedResult = expectedArray.get(hit.getId());
assertThat("for doc " + hit.getId(), result, equalTo(expectedResult));
if (expectedResult != null) {
Expand Down
Expand Up @@ -298,12 +298,12 @@ public void testScriptFieldUsingSource() throws Exception {
assertThat(sObj2Arr2.get(0).toString(), equalTo("arr_value1"));
assertThat(sObj2Arr2.get(1).toString(), equalTo("arr_value2"));

sObj2Arr2 = response.getHits().getAt(0).field("s_obj2_arr2").value();
sObj2Arr2 = response.getHits().getAt(0).field("s_obj2_arr2").values();
assertThat(sObj2Arr2.size(), equalTo(2));
assertThat(sObj2Arr2.get(0).toString(), equalTo("arr_value1"));
assertThat(sObj2Arr2.get(1).toString(), equalTo("arr_value2"));

List sObj2Arr3 = response.getHits().getAt(0).field("s_arr3").value();
List sObj2Arr3 = response.getHits().getAt(0).field("s_arr3").values();
assertThat(((Map) sObj2Arr3.get(0)).get("arr3_field1").toString(), equalTo("arr3_value1"));
}

Expand Down

0 comments on commit 8346e92

Please sign in to comment.