Skip to content

Commit 3b7928d

Browse files
committed
Mappings: Lock down _field_names field
Now that we have an explicit `enabled` flag, we can lock down the field type so it is not mungeable. see #8143 closes #9912
1 parent 7181bbd commit 3b7928d

File tree

8 files changed

+32
-18
lines changed

8 files changed

+32
-18
lines changed

docs/reference/migration/migrate_2_0.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ to provide special features. They now have limited configuration options.
256256
* `_index` configuration is limited to enabling the field.
257257
* `_routing` configuration is limited to requiring the field.
258258
* `_boost` has been removed.
259+
* `_field_names` configuration is limited to disabling the field.
259260

260261
=== Codecs
261262

src/main/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public Builder() {
8989
}
9090

9191
@Override
92+
@Deprecated
9293
public Builder index(boolean index) {
9394
enabled(index);
9495
return super.index(index);
@@ -113,7 +114,9 @@ public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext
113114
}
114115

115116
FieldNamesFieldMapper.Builder builder = fieldNames();
116-
parseField(builder, builder.name, node, parserContext);
117+
if (parserContext.indexVersionCreated().before(Version.V_2_0_0)) {
118+
parseField(builder, builder.name, node, parserContext);
119+
}
117120

118121
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
119122
Map.Entry<String, Object> entry = iterator.next();
@@ -260,7 +263,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
260263
if (includeDefaults || enabledState != Defaults.ENABLED_STATE) {
261264
builder.field("enabled", enabledState.enabled);
262265
}
263-
if (includeDefaults || fieldType().equals(Defaults.FIELD_TYPE) == false) {
266+
if (writePre2xSettings && (includeDefaults || fieldType().equals(Defaults.FIELD_TYPE) == false)) {
264267
super.doXContentBody(builder, includeDefaults, params);
265268
}
266269

src/main/java/org/elasticsearch/index/query/ExistsFilterParser.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.elasticsearch.common.lucene.search.Queries;
2929
import org.elasticsearch.common.lucene.search.XBooleanFilter;
3030
import org.elasticsearch.common.xcontent.XContentParser;
31+
import org.elasticsearch.index.mapper.FieldMapper;
3132
import org.elasticsearch.index.mapper.FieldMappers;
3233
import org.elasticsearch.index.mapper.MapperService;
3334
import org.elasticsearch.index.mapper.internal.FieldNamesFieldMapper;
@@ -82,7 +83,8 @@ public Filter parse(QueryParseContext parseContext) throws IOException, QueryPar
8283
}
8384

8485
public static Filter newFilter(QueryParseContext parseContext, String fieldPattern, String filterName) {
85-
final FieldMappers fieldNamesMapper = parseContext.mapperService().indexName(FieldNamesFieldMapper.CONTENT_TYPE);
86+
final FieldMappers fieldNamesMappers = parseContext.mapperService().indexName(FieldNamesFieldMapper.NAME);
87+
final FieldNamesFieldMapper fieldNamesMapper = (FieldNamesFieldMapper)fieldNamesMappers.mapper();
8688

8789
MapperService.SmartNameObjectMapper smartNameObjectMapper = parseContext.smartObjectMapper(fieldPattern);
8890
if (smartNameObjectMapper != null && smartNameObjectMapper.hasMapper()) {
@@ -104,14 +106,14 @@ public static Filter newFilter(QueryParseContext parseContext, String fieldPatte
104106
nonNullFieldMappers = smartNameFieldMappers;
105107
}
106108
Filter filter = null;
107-
if (fieldNamesMapper!= null && fieldNamesMapper.mapper().fieldType().indexOptions() != IndexOptions.NONE) {
109+
if (fieldNamesMapper!= null && fieldNamesMapper.enabled()) {
108110
final String f;
109111
if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) {
110112
f = smartNameFieldMappers.mapper().names().indexName();
111113
} else {
112114
f = field;
113115
}
114-
filter = fieldNamesMapper.mapper().termFilter(f, parseContext);
116+
filter = fieldNamesMapper.termFilter(f, parseContext);
115117
}
116118
// if _field_names are not indexed, we need to go the slow way
117119
if (filter == null && smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) {

src/main/java/org/elasticsearch/index/query/MissingFilterParser.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ public static Filter newFilter(QueryParseContext parseContext, String fieldPatte
9595
throw new QueryParsingException(parseContext.index(), "missing must have either existence, or null_value, or both set to true");
9696
}
9797

98-
final FieldMappers fieldNamesMapper = parseContext.mapperService().indexName(FieldNamesFieldMapper.NAME);
98+
final FieldMappers fieldNamesMappers = parseContext.mapperService().indexName(FieldNamesFieldMapper.NAME);
99+
final FieldNamesFieldMapper fieldNamesMapper = (FieldNamesFieldMapper)fieldNamesMappers.mapper();
99100
MapperService.SmartNameObjectMapper smartNameObjectMapper = parseContext.smartObjectMapper(fieldPattern);
100101
if (smartNameObjectMapper != null && smartNameObjectMapper.hasMapper()) {
101102
// automatic make the object mapper pattern
@@ -124,14 +125,14 @@ public static Filter newFilter(QueryParseContext parseContext, String fieldPatte
124125
nonNullFieldMappers = smartNameFieldMappers;
125126
}
126127
Filter filter = null;
127-
if (fieldNamesMapper != null && fieldNamesMapper.mapper().fieldType().indexOptions() != IndexOptions.NONE) {
128+
if (fieldNamesMapper != null && fieldNamesMapper.enabled()) {
128129
final String f;
129130
if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) {
130131
f = smartNameFieldMappers.mapper().names().indexName();
131132
} else {
132133
f = field;
133134
}
134-
filter = fieldNamesMapper.mapper().termFilter(f, parseContext);
135+
filter = fieldNamesMapper.termFilter(f, parseContext);
135136
}
136137
// if _field_names are not indexed, we need to go the slow way
137138
if (filter == null && smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) {

src/test/java/org/elasticsearch/get/GetActionTests.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,16 +1144,20 @@ public void testGeneratedStringFieldsUnstored() throws IOException {
11441144
@Test
11451145
public void testGeneratedStringFieldsStored() throws IOException {
11461146
indexSingleDocumentWithStringFieldsGeneratedFromText(true, randomBoolean());
1147-
String[] fieldsList = {"_all", "_field_names"};
1147+
String[] fieldsList = {"_all"};
1148+
String[] alwaysNotStoredFieldsList = {"_field_names"};
11481149
// before refresh - document is only in translog
11491150
assertGetFieldsNull(indexOrAlias(), "doc", "1", fieldsList);
11501151
assertGetFieldsException(indexOrAlias(), "doc", "1", fieldsList);
1152+
assertGetFieldsNull(indexOrAlias(), "doc", "1", alwaysNotStoredFieldsList);
11511153
refresh();
11521154
//after refresh - document is in translog and also indexed
11531155
assertGetFieldsAlwaysWorks(indexOrAlias(), "doc", "1", fieldsList);
1156+
assertGetFieldsNull(indexOrAlias(), "doc", "1", alwaysNotStoredFieldsList);
11541157
flush();
11551158
//after flush - document is in not anymore translog - only indexed
11561159
assertGetFieldsAlwaysWorks(indexOrAlias(), "doc", "1", fieldsList);
1160+
assertGetFieldsNull(indexOrAlias(), "doc", "1", alwaysNotStoredFieldsList);
11571161
}
11581162

11591163
void indexSingleDocumentWithStringFieldsGeneratedFromText(boolean stored, boolean sourceEnabled) {
@@ -1167,8 +1171,7 @@ void indexSingleDocumentWithStringFieldsGeneratedFromText(boolean stored, boolea
11671171
" \"mappings\": {\n" +
11681172
" \"doc\": {\n" +
11691173
" \"_source\" : {\"enabled\" : " + sourceEnabled + "}," +
1170-
" \"_all\" : {\"enabled\" : true, \"store\":\"" + storedString + "\" }," +
1171-
" \"_field_names\" : {\"store\":\"" + storedString + "\" }" +
1174+
" \"_all\" : {\"enabled\" : true, \"store\":\"" + storedString + "\" }" +
11721175
" }\n" +
11731176
" }\n" +
11741177
"}";

src/test/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapperTests.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
package org.elasticsearch.index.mapper.internal;
2121

22+
import org.elasticsearch.Version;
23+
import org.elasticsearch.cluster.metadata.IndexMetaData;
24+
import org.elasticsearch.common.settings.ImmutableSettings;
25+
import org.elasticsearch.common.settings.Settings;
2226
import org.elasticsearch.common.xcontent.XContentFactory;
2327
import org.elasticsearch.index.mapper.DocumentMapper;
2428
import org.elasticsearch.index.mapper.DocumentMapperParser;
@@ -114,7 +118,8 @@ public void testDisablingBackcompat() throws Exception {
114118
.startObject("_field_names").field("index", "no").endObject()
115119
.endObject().endObject().string();
116120

117-
DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser().parse(mapping);
121+
Settings indexSettings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build();
122+
DocumentMapper docMapper = createIndex("test", indexSettings).mapperService().documentMapperParser().parse(mapping);
118123
FieldNamesFieldMapper fieldNamesMapper = docMapper.rootMapper(FieldNamesFieldMapper.class);
119124
assertFalse(fieldNamesMapper.enabled());
120125

@@ -127,12 +132,13 @@ public void testDisablingBackcompat() throws Exception {
127132
assertNull(doc.rootDoc().get("_field_names"));
128133
}
129134

130-
public void testFieldTypeSettings() throws Exception {
135+
public void testFieldTypeSettingsBackcompat() throws Exception {
131136
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
132137
.startObject("_field_names").field("store", "yes").endObject()
133138
.endObject().endObject().string();
134139

135-
DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser().parse(mapping);
140+
Settings indexSettings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build();
141+
DocumentMapper docMapper = createIndex("test", indexSettings).mapperService().documentMapperParser().parse(mapping);
136142
FieldNamesFieldMapper fieldNamesMapper = docMapper.rootMapper(FieldNamesFieldMapper.class);
137143
assertTrue(fieldNamesMapper.fieldType().stored());
138144
}

src/test/java/org/elasticsearch/search/query/ExistsMissingTests.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ public void testExistsMissing() throws Exception {
4545
.startObject()
4646
.startObject("type")
4747
.startObject(FieldNamesFieldMapper.NAME)
48-
// by setting randomly index to no we also test the pre-1.3 behavior
49-
.field("index", randomFrom("no", "not_analyzed"))
50-
.field("store", randomFrom("no", "yes"))
48+
.field("enabled", randomBoolean())
5149
.endObject()
5250
.startObject("properties")
5351
.startObject("foo")

src/test/java/org/elasticsearch/test/ElasticsearchIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ private void randomIndexTemplate() throws IOException {
335335
.field("compress", randomBoolean())
336336
.endObject();
337337
}
338-
if (compatibilityVersion().onOrAfter(Version.V_1_3_0)) {
338+
if (compatibilityVersion().onOrAfter(Version.V_1_3_0) && compatibilityVersion().before(Version.V_2_0_0)) {
339339
// some tests rely on this BWC version behavior that we wanna keep
340340
mappings.startObject(FieldNamesFieldMapper.NAME)
341341
.startObject("fielddata")

0 commit comments

Comments
 (0)