Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only allow one type on 6.0 indices #24317

Merged
merged 7 commits into from
Apr 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings {
MapperService.INDEX_MAPPING_NESTED_FIELDS_LIMIT_SETTING,
MapperService.INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING,
MapperService.INDEX_MAPPING_DEPTH_LIMIT_SETTING,
MapperService.INDEX_MAPPING_SINGLE_TYPE_SETTING,
BitsetFilterCache.INDEX_LOAD_RANDOM_ACCESS_FILTERS_EAGERLY_SETTING,
IndexModule.INDEX_STORE_TYPE_SETTING,
IndexModule.INDEX_STORE_PRE_LOAD_SETTING,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.DelegatingAnalyzerWrapper;
import org.elasticsearch.ElasticsearchGenerationException;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
Expand Down Expand Up @@ -94,6 +96,19 @@ public enum MergeReason {
public static final boolean INDEX_MAPPER_DYNAMIC_DEFAULT = true;
public static final Setting<Boolean> INDEX_MAPPER_DYNAMIC_SETTING =
Setting.boolSetting("index.mapper.dynamic", INDEX_MAPPER_DYNAMIC_DEFAULT, Property.Dynamic, Property.IndexScope);
public static final Setting<Boolean> INDEX_MAPPING_SINGLE_TYPE_SETTING;
static {
Function<Settings, String> defValue = settings -> {
// TODO: uncomment this
/*boolean singleType = true;
if (settings.getAsVersion(IndexMetaData.SETTING_VERSION_CREATED, null) != null) {
singleType = Version.indexCreated(settings).onOrAfter(Version.V_6_0_0_alpha1_UNRELEASED);
}*/
boolean singleType = false;
return Boolean.valueOf(singleType).toString();
};
INDEX_MAPPING_SINGLE_TYPE_SETTING = Setting.boolSetting("index.mapping.single_type", defValue, Property.IndexScope, Property.Final);
}
private static ObjectHashSet<String> META_FIELDS = ObjectHashSet.from(
"_uid", "_id", "_type", "_all", "_parent", "_routing", "_index",
"_size", "_timestamp", "_ttl"
Expand Down Expand Up @@ -457,6 +472,15 @@ private synchronized Map<String, DocumentMapper> internalMerge(@Nullable Documen
}
}

if (indexSettings.getValue(INDEX_MAPPING_SINGLE_TYPE_SETTING)) {
Set<String> actualTypes = new HashSet<>(mappers.keySet());
actualTypes.remove(DEFAULT_MAPPING);
if (actualTypes.size() > 1) {
throw new IllegalArgumentException(
"Rejecting mapping update to [" + index().getName() + "] as the final mapping would have more than 1 type: " + actualTypes);
}
}

// make structures immutable
mappers = Collections.unmodifiableMap(mappers);
results = Collections.unmodifiableMap(results);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public void testCreateShrinkIndex() {
.put("index.version.created", version)
).get();
for (int i = 0; i < 20; i++) {
client().prepareIndex("source", randomFrom("t1", "t2", "t3"))
client().prepareIndex("source", "type")
.setSource("{\"foo\" : \"bar\", \"i\" : " + i + "}", XContentType.JSON).get();
}
ImmutableOpenMap<String, DiscoveryNode> dataNodes = client().admin().cluster().prepareState().get().getState().nodes()
Expand Down Expand Up @@ -179,7 +179,7 @@ public void testCreateShrinkIndex() {
}

for (int i = 20; i < 40; i++) {
client().prepareIndex("target", randomFrom("t1", "t2", "t3"))
client().prepareIndex("target", "type")
.setSource("{\"foo\" : \"bar\", \"i\" : " + i + "}", XContentType.JSON).get();
}
flushAndRefresh();
Expand All @@ -197,7 +197,7 @@ public void testCreateShrinkIndexFails() throws Exception {
.put("number_of_shards", randomIntBetween(2, 7))
.put("number_of_replicas", 0)).get();
for (int i = 0; i < 20; i++) {
client().prepareIndex("source", randomFrom("t1", "t2", "t3"))
client().prepareIndex("source", "type")
.setSource("{\"foo\" : \"bar\", \"i\" : " + i + "}", XContentType.JSON).get();
}
ImmutableOpenMap<String, DiscoveryNode> dataNodes = client().admin().cluster().prepareState().get().getState().nodes()
Expand Down Expand Up @@ -275,10 +275,10 @@ public void testCreateShrinkWithIndexSort() throws Exception {
.put("number_of_shards", 8)
.put("number_of_replicas", 0)
)
.addMapping("t1", "id", "type=keyword,doc_values=true")
.addMapping("type", "id", "type=keyword,doc_values=true")
.get();
for (int i = 0; i < 20; i++) {
client().prepareIndex("source", "t1", Integer.toString(i))
client().prepareIndex("source", "type", Integer.toString(i))
.setSource("{\"foo\" : \"bar\", \"id\" : " + i + "}", XContentType.JSON).get();
}
ImmutableOpenMap<String, DiscoveryNode> dataNodes = client().admin().cluster().prepareState().get().getState().nodes()
Expand Down Expand Up @@ -326,7 +326,7 @@ public void testCreateShrinkWithIndexSort() throws Exception {

// ... and that the index sort is also applied to updates
for (int i = 20; i < 40; i++) {
client().prepareIndex("target", randomFrom("t1", "t2", "t3"))
client().prepareIndex("target", "type")
.setSource("{\"foo\" : \"bar\", \"i\" : " + i + "}", XContentType.JSON).get();
}
flushAndRefresh();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ public void testBulkIndexingWhileInitializing() throws Exception {
*/
public void testBulkUpdateDocAsUpsertWithParent() throws Exception {
client().admin().indices().prepareCreate("test")
.setSettings("index.mapping.single_type", false)
.addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
.addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON)
.execute().actionGet();
Expand Down Expand Up @@ -519,6 +520,7 @@ public void testBulkUpdateDocAsUpsertWithParent() throws Exception {
*/
public void testBulkUpdateUpsertWithParent() throws Exception {
assertAcked(prepareCreate("test")
.setSettings("index.mapping.single_type", false)
.addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
.addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON));
ensureGreen();
Expand Down Expand Up @@ -603,8 +605,10 @@ public void testBulkUpdateUpsertWithParent() throws Exception {
* Test for https://github.com/elastic/elasticsearch/issues/8365
*/
public void testBulkUpdateChildMissingParentRouting() throws Exception {
assertAcked(prepareCreate("test").addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
.addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON));
assertAcked(prepareCreate("test")
.setSettings("index.mapping.single_type", false)
.addMapping("parent", "{\"parent\":{}}", XContentType.JSON)
.addMapping("child", "{\"child\": {\"_parent\": {\"type\": \"parent\"}}}", XContentType.JSON));
ensureGreen();

BulkRequestBuilder builder = client().prepareBulk();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,7 @@ public void testAliasFilterWithNowInRangeFilterAndQuery() throws Exception {

public void testAliasesFilterWithHasChildQuery() throws Exception {
assertAcked(prepareCreate("my-index")
.setSettings("index.mapping.single_type", false)
.addMapping("parent")
.addMapping("child", "_parent", "type=parent")
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public void testAddChildTypePointingToAlreadyExistingType() throws Exception {
// Tests _parent meta field logic, because part of the validation is in MetaDataMappingService
public void testAddExtraChildTypePointingToAlreadyParentExistingType() throws Exception {
IndexService indexService = createIndex("test", client().admin().indices().prepareCreate("test")
.setSettings("index.mapping.single_type", false)
.addMapping("parent")
.addMapping("child1", "_parent", "type=parent")
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,9 @@ public void testMerge_notAvailable() {

public void testNumberFiltering() {
createIndex("test1", Settings.EMPTY, "type", "value", "type=long");
client().prepareIndex("test1", "test").setSource("value", 1L).get();
client().prepareIndex("test1", "type").setSource("value", 1L).get();
createIndex("test2", Settings.EMPTY, "type", "value", "type=long");
client().prepareIndex("test2", "test").setSource("value", 3L).get();
client().prepareIndex("test2", "type").setSource("value", 3L).get();
client().admin().indices().prepareRefresh().get();

FieldStatsResponse response = client().prepareFieldStats()
Expand Down Expand Up @@ -426,10 +426,10 @@ public void testDateFiltering() {
String dateTime2Str = DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.parser().print(dateTime2);

createIndex("test1", Settings.EMPTY, "type", "value", "type=date", "value2", "type=date,index=false");
client().prepareIndex("test1", "test")
client().prepareIndex("test1", "type")
.setSource("value", dateTime1Str, "value2", dateTime1Str).get();
createIndex("test2", Settings.EMPTY, "type", "value", "type=date");
client().prepareIndex("test2", "test").setSource("value", dateTime2Str).get();
client().prepareIndex("test2", "type").setSource("value", dateTime2Str).get();
client().admin().indices().prepareRefresh().get();

FieldStatsResponse response = client().prepareFieldStats()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ public void testLatestVersionLoaded() throws Exception {
// clean two nodes
internalCluster().startNodes(2, Settings.builder().put("gateway.recover_after_nodes", 2).build());

assertAcked(client().admin().indices().prepareCreate("test").setSettings("index.mapping.single_type", false));
client().prepareIndex("test", "type1", "1").setSource(jsonBuilder().startObject().field("field", "value1").endObject()).execute().actionGet();
client().admin().indices().prepareFlush().execute().actionGet();
client().prepareIndex("test", "type1", "2").setSource(jsonBuilder().startObject().field("field", "value2").endObject()).execute().actionGet();
Expand Down
11 changes: 6 additions & 5 deletions core/src/test/java/org/elasticsearch/get/GetActionIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.engine.VersionConflictEngineException;
Expand Down Expand Up @@ -255,7 +254,7 @@ public void testGetDocWithMultivaluedFields() throws Exception {
assertAcked(prepareCreate("test")
.addMapping("type1", mapping1, XContentType.JSON)
.addMapping("type2", mapping2, XContentType.JSON)
.setSettings(Settings.builder().put("index.refresh_interval", -1)));
.setSettings("index.refresh_interval", -1, "index.mapping.single_type", false));
ensureGreen();

GetResponse response = client().prepareGet("test", "type1", "1").get();
Expand Down Expand Up @@ -530,7 +529,7 @@ public void testGetFieldsMetaData() throws Exception {
.addMapping("parent")
.addMapping("my-type1", "_parent", "type=parent", "field1", "type=keyword,store=true")
.addAlias(new Alias("alias"))
.setSettings(Settings.builder().put("index.refresh_interval", -1)));
.setSettings("index.refresh_interval", -1, "index.mapping.single_type", false));

client().prepareIndex("test", "my-type1", "1")
.setRouting("1")
Expand Down Expand Up @@ -594,7 +593,7 @@ public void testGetFieldsNonLeafField() throws Exception {

public void testGetFieldsComplexField() throws Exception {
assertAcked(prepareCreate("my-index")
.setSettings(Settings.builder().put("index.refresh_interval", -1))
.setSettings("index.refresh_interval", -1, "index.mapping.single_type", false)
.addMapping("my-type2", jsonBuilder().startObject().startObject("my-type2").startObject("properties")
.startObject("field1").field("type", "object").startObject("properties")
.startObject("field2").field("type", "object").startObject("properties")
Expand Down Expand Up @@ -726,6 +725,7 @@ public void testUngeneratedFieldsThatAreAlwaysStored() throws IOException {
String createIndexSource = "{\n" +
" \"settings\": {\n" +
" \"index.translog.flush_threshold_size\": \"1pb\",\n" +
" \"index.mapping.single_type\": false," +
" \"refresh_interval\": \"-1\"\n" +
" },\n" +
" \"mappings\": {\n" +
Expand All @@ -738,7 +738,8 @@ public void testUngeneratedFieldsThatAreAlwaysStored() throws IOException {
" }\n" +
" }\n" +
"}";
assertAcked(prepareCreate("test").addAlias(new Alias("alias")).setSource(createIndexSource, XContentType.JSON));
assertAcked(prepareCreate("test")
.addAlias(new Alias("alias")).setSource(createIndexSource, XContentType.JSON));
ensureGreen();

client().prepareIndex("test", "doc").setId("1").setSource("{}", XContentType.JSON).setParent("1").get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.RAMDirectory;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
Expand All @@ -41,6 +43,7 @@
import org.elasticsearch.index.mapper.KeywordFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.Mapper.BuilderContext;
import org.elasticsearch.index.mapper.MapperService.MergeReason;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.NumberFieldMapper;
import org.elasticsearch.index.mapper.ParentFieldMapper;
Expand Down Expand Up @@ -131,7 +134,7 @@ public <IFD extends IndexFieldData<?>> IFD getForField(String type, String field

@Before
public void setup() throws Exception {
indexService = createIndex("test");
indexService = createIndex("test", Settings.builder().put("mapping.single_type", false).build());
mapperService = indexService.mapperService();
indicesFieldDataCache = getInstanceFromNode(IndicesService.class).getIndicesFieldDataCache();
ifdService = indexService.fieldData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private static void assertMappingsHaveField(GetMappingsResponse mappings, String
}

public void testMappingsPropagatedToMasterNodeImmediately() throws IOException {
createIndex("index");
assertAcked(prepareCreate("index").setSettings("index.mapping.single_type", false));

// works when the type has been dynamically created
client().prepareIndex("index", "type", "1").setSource("foo", 3).get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.BooleanFieldMapper.BooleanFieldType;
import org.elasticsearch.index.mapper.DateFieldMapper.DateFieldType;
import org.elasticsearch.index.mapper.MapperService.MergeReason;
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberFieldType;
import org.elasticsearch.test.ESSingleNodeTestCase;

Expand Down Expand Up @@ -524,7 +525,7 @@ public void testReuseExistingMappings() throws IOException, Exception {
}

public void testMixTemplateMultiFieldAndMappingReuse() throws Exception {
IndexService indexService = createIndex("test");
IndexService indexService = createIndex("test", Settings.builder().put("mapping.single_type", false).build());
XContentBuilder mappings1 = jsonBuilder().startObject()
.startObject("type1")
.startArray("dynamic_templates")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
package org.elasticsearch.index.mapper;

import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
Expand All @@ -30,6 +29,7 @@
import org.elasticsearch.index.mapper.MapperService.MergeReason;
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberFieldType;
import org.elasticsearch.test.ESSingleNodeTestCase;
import org.hamcrest.Matchers;

import java.io.IOException;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -74,7 +74,7 @@ public void testTypeNameTooLong() {
}

public void testTypes() throws Exception {
IndexService indexService1 = createIndex("index1");
IndexService indexService1 = createIndex("index1", Settings.builder().put("index.mapping.single_type", false).build());
MapperService mapperService = indexService1.mapperService();
assertEquals(Collections.emptySet(), mapperService.types());

Expand Down Expand Up @@ -207,7 +207,7 @@ public void testMergeParentTypesSame() {
}

public void testOtherDocumentMappersOnlyUpdatedWhenChangingFieldType() throws IOException {
IndexService indexService = createIndex("test");
IndexService indexService = createIndex("test", Settings.builder().put("index.mapping.single_type", false).build());

CompressedXContent simpleMapping = new CompressedXContent(XContentFactory.jsonBuilder().startObject()
.startObject("properties")
Expand Down Expand Up @@ -309,4 +309,16 @@ public void testIndexSortWithNestedFields() throws IOException {
assertThat(invalidNestedException.getMessage(),
containsString("cannot have nested fields when index sort is activated"));
}

@AwaitsFix(bugUrl="https://github.com/elastic/elasticsearch/pull/24317#issuecomment-297624290")
public void testForbidMultipleTypes() throws IOException {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject().string();
MapperService mapperService = createIndex("test").mapperService();
mapperService.merge("type", new CompressedXContent(mapping), MergeReason.MAPPING_UPDATE, randomBoolean());

String mapping2 = XContentFactory.jsonBuilder().startObject().startObject("type2").endObject().endObject().string();
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> mapperService.merge("type2", new CompressedXContent(mapping2), MergeReason.MAPPING_UPDATE, randomBoolean()));
assertThat(e.getMessage(), Matchers.startsWith("Rejecting mapping update to [test] as the final mapping would have more than 1 type: "));
}
}
Loading