Improve the error message when loading text fielddata. (#52753)

Emphasize keyword over fielddata as the preferred way to use String fields for aggregations or sorting.
This commit is contained in:
Sachin Frayne 2020-02-25 23:28:51 +00:00 committed by Julie Tibshirani
parent 662f21fcea
commit d3c0a2f013
3 changed files with 24 additions and 23 deletions

View File

@ -37,33 +37,33 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class GraphIT extends ESRestHighLevelClientTestCase { public class GraphIT extends ESRestHighLevelClientTestCase {
@Before @Before
public void indexDocuments() throws IOException { public void indexDocuments() throws IOException {
// Create chain of doc IDs across indices 1->2->3 // Create chain of doc IDs across indices 1->2->3
Request doc1 = new Request(HttpPut.METHOD_NAME, "/index1/_doc/1"); Request doc1 = new Request(HttpPut.METHOD_NAME, "/index1/_doc/1");
doc1.setJsonEntity("{ \"num\":[1], \"const\":\"start\"}"); doc1.setJsonEntity("{ \"num\":[1], \"const\":\"start\"}");
client().performRequest(doc1); client().performRequest(doc1);
Request doc2 = new Request(HttpPut.METHOD_NAME, "/index2/_doc/1"); Request doc2 = new Request(HttpPut.METHOD_NAME, "/index2/_doc/1");
doc2.setJsonEntity("{\"num\":[1,2], \"const\":\"foo\"}"); doc2.setJsonEntity("{\"num\":[1,2], \"const\":\"foo\"}");
client().performRequest(doc2); client().performRequest(doc2);
Request doc3 = new Request(HttpPut.METHOD_NAME, "/index2/_doc/2"); Request doc3 = new Request(HttpPut.METHOD_NAME, "/index2/_doc/2");
doc3.setJsonEntity("{\"num\":[2,3], \"const\":\"foo\"}"); doc3.setJsonEntity("{\"num\":[2,3], \"const\":\"foo\"}");
client().performRequest(doc3); client().performRequest(doc3);
Request doc4 = new Request(HttpPut.METHOD_NAME, "/index_no_field_data/_doc/2"); Request doc4 = new Request(HttpPut.METHOD_NAME, "/index_no_field_data/_doc/2");
doc4.setJsonEntity("{\"num\":\"string\", \"const\":\"foo\"}"); doc4.setJsonEntity("{\"num\":\"string\", \"const\":\"foo\"}");
client().performRequest(doc4); client().performRequest(doc4);
Request doc5 = new Request(HttpPut.METHOD_NAME, "/index_no_field_data/_doc/2"); Request doc5 = new Request(HttpPut.METHOD_NAME, "/index_no_field_data/_doc/2");
doc5.setJsonEntity("{\"num\":[2,4], \"const\":\"foo\"}"); doc5.setJsonEntity("{\"num\":[2,4], \"const\":\"foo\"}");
client().performRequest(doc5); client().performRequest(doc5);
client().performRequest(new Request(HttpPost.METHOD_NAME, "/_refresh")); client().performRequest(new Request(HttpPost.METHOD_NAME, "/_refresh"));
} }
public void testCleanExplore() throws Exception { public void testCleanExplore() throws Exception {
GraphExploreRequest graphExploreRequest = new GraphExploreRequest(); GraphExploreRequest graphExploreRequest = new GraphExploreRequest();
@ -75,7 +75,7 @@ public class GraphIT extends ESRestHighLevelClientTestCase {
if (i == 0) { if (i == 0) {
guidingQuery = new TermQueryBuilder("const.keyword", "start"); guidingQuery = new TermQueryBuilder("const.keyword", "start");
} else if (randomBoolean()){ } else if (randomBoolean()){
guidingQuery = new TermQueryBuilder("const.keyword", "foo"); guidingQuery = new TermQueryBuilder("const.keyword", "foo");
} }
Hop hop = graphExploreRequest.createNextHop(guidingQuery); Hop hop = graphExploreRequest.createNextHop(guidingQuery);
VertexRequest vr = hop.addVertexRequest("num"); VertexRequest vr = hop.addVertexRequest("num");
@ -94,13 +94,13 @@ public class GraphIT extends ESRestHighLevelClientTestCase {
} }
assertEquals(expectedTermsAndDepths, actualTermsAndDepths); assertEquals(expectedTermsAndDepths, actualTermsAndDepths);
assertThat(exploreResponse.isTimedOut(), Matchers.is(false)); assertThat(exploreResponse.isTimedOut(), Matchers.is(false));
ShardOperationFailedException[] failures = exploreResponse.getShardFailures(); ShardOperationFailedException[] failures = exploreResponse.getShardFailures();
assertThat(failures.length, Matchers.equalTo(0)); assertThat(failures.length, Matchers.equalTo(0));
} }
public void testBadExplore() throws Exception { public void testBadExplore() throws Exception {
//Explore indices where lack of fielddata=true on one index leads to partial failures //Explore indices where lack of fielddata=true on one index leads to partial failures
GraphExploreRequest graphExploreRequest = new GraphExploreRequest(); GraphExploreRequest graphExploreRequest = new GraphExploreRequest();
graphExploreRequest.indices("index1", "index2", "index_no_field_data"); graphExploreRequest.indices("index1", "index2", "index_no_field_data");
graphExploreRequest.useSignificance(false); graphExploreRequest.useSignificance(false);
@ -110,7 +110,7 @@ public class GraphIT extends ESRestHighLevelClientTestCase {
if (i == 0) { if (i == 0) {
guidingQuery = new TermQueryBuilder("const.keyword", "start"); guidingQuery = new TermQueryBuilder("const.keyword", "start");
} else if (randomBoolean()){ } else if (randomBoolean()){
guidingQuery = new TermQueryBuilder("const.keyword", "foo"); guidingQuery = new TermQueryBuilder("const.keyword", "foo");
} }
Hop hop = graphExploreRequest.createNextHop(guidingQuery); Hop hop = graphExploreRequest.createNextHop(guidingQuery);
VertexRequest vr = hop.addVertexRequest("num"); VertexRequest vr = hop.addVertexRequest("num");
@ -131,9 +131,9 @@ public class GraphIT extends ESRestHighLevelClientTestCase {
assertThat(exploreResponse.isTimedOut(), Matchers.is(false)); assertThat(exploreResponse.isTimedOut(), Matchers.is(false));
ShardOperationFailedException[] failures = exploreResponse.getShardFailures(); ShardOperationFailedException[] failures = exploreResponse.getShardFailures();
assertThat(failures.length, Matchers.equalTo(1)); assertThat(failures.length, Matchers.equalTo(1));
assertTrue(failures[0].reason().contains("Fielddata is disabled")); assertTrue(failures[0].reason().contains("Text fields are not optimised for operations that require per-document field data"));
} }
} }

View File

@ -757,9 +757,10 @@ public class TextFieldMapper extends FieldMapper {
@Override @Override
public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName) { public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName) {
if (fielddata == false) { if (fielddata == false) {
throw new IllegalArgumentException("Fielddata is disabled on text fields by default. Set fielddata=true on [" + name() throw new IllegalArgumentException("Text fields are not optimised for operations that require per-document "
+ "] in order to load fielddata in memory by uninverting the inverted index. Note that this can however " + "field data like aggregations and sorting, so these operations are disabled by default. Please use a "
+ "use significant memory. Alternatively use a keyword field instead."); + "keyword field instead. Alternatively, set fielddata=true on [" + name() + "] in order to load "
+ "field data by uninverting the inverted index. Note that this can use significant memory.");
} }
return new PagedBytesIndexFieldData.Builder(fielddataMinFrequency, fielddataMaxFrequency, fielddataMinSegmentSize); return new PagedBytesIndexFieldData.Builder(fielddataMinFrequency, fielddataMaxFrequency, fielddataMinSegmentSize);
} }

View File

@ -516,7 +516,7 @@ public class TextFieldMapperTests extends ESSingleNodeTestCase {
FieldMapper fieldMapper = (FieldMapper) disabledMapper.mappers().getMapper("field"); FieldMapper fieldMapper = (FieldMapper) disabledMapper.mappers().getMapper("field");
fieldMapper.fieldType().fielddataBuilder("test"); fieldMapper.fieldType().fielddataBuilder("test");
}); });
assertThat(e.getMessage(), containsString("Fielddata is disabled")); assertThat(e.getMessage(), containsString("Text fields are not optimised for operations that require per-document field data"));
mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type") mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("field") .startObject("properties").startObject("field")