Skip to content

Commit a560919

Browse files
authored
Allow dynamic defaults in mappings of managed system indices (#133262)
System indices with non-dynamic mappings normally reject `put mapping` requests that attempt to modify the mapping of a managed index. However, for fields like `dense_vector` and `semantic_text`, some mapping options depend on the shape of the ingested data. The first ingestion often requires a dynamic update to set these defaults. To support this for system indices, this change marks the relevant `put mapping` requests as originating from bulk ingestion, which bypasses the system index mapping check. This is safe because: * such updates are already validated against invalid dynamic updates, and * an error would be raised earlier if a new field is added when `dynamic` is disabled. Fixes #133171
1 parent f6e2092 commit a560919

File tree

3 files changed

+45
-8
lines changed

3 files changed

+45
-8
lines changed

server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ protected Collection<Class<? extends Plugin>> nodePlugins() {
8484
* settings when it is first used, when it is referenced via its alias.
8585
*/
8686
public void testSystemIndexIsAutoCreatedViaAlias() {
87-
doCreateTest(() -> indexDoc(INDEX_NAME, "1", "foo", "bar"), PRIMARY_INDEX_NAME);
87+
doCreateTest(() -> indexDoc(INDEX_NAME, "1", "foo", "bar"), PRIMARY_INDEX_NAME, false);
8888
}
8989

9090
/**
@@ -93,7 +93,7 @@ public void testSystemIndexIsAutoCreatedViaAlias() {
9393
* index name.
9494
*/
9595
public void testSystemIndexIsAutoCreatedViaConcreteName() {
96-
doCreateTest(() -> indexDoc(PRIMARY_INDEX_NAME, "1", "foo", "bar"), PRIMARY_INDEX_NAME);
96+
doCreateTest(() -> indexDoc(PRIMARY_INDEX_NAME, "1", "foo", "bar"), PRIMARY_INDEX_NAME, false);
9797
}
9898

9999
/**
@@ -144,7 +144,7 @@ public void testNonPrimarySystemIndexCreationThrowsError() {
144144
* settings when it is explicitly created, when it is referenced via its alias.
145145
*/
146146
public void testCreateSystemIndexViaAlias() {
147-
doCreateTest(() -> assertAcked(prepareCreate(INDEX_NAME)), PRIMARY_INDEX_NAME);
147+
doCreateTest(() -> assertAcked(prepareCreate(INDEX_NAME)), PRIMARY_INDEX_NAME, false);
148148
}
149149

150150
/**
@@ -153,7 +153,11 @@ public void testCreateSystemIndexViaAlias() {
153153
* concrete index name.
154154
*/
155155
public void testCreateSystemIndexViaConcreteName() {
156-
doCreateTest(() -> assertAcked(prepareCreate(PRIMARY_INDEX_NAME)), PRIMARY_INDEX_NAME);
156+
doCreateTest(() -> assertAcked(prepareCreate(PRIMARY_INDEX_NAME)), PRIMARY_INDEX_NAME, false);
157+
}
158+
159+
public void testSystemIndexIsAutoCreatedWithDynamicDefault() {
160+
doCreateTest(() -> indexDoc(PRIMARY_INDEX_NAME, "1", "vector", new int[] { 1, 2, 3 }), PRIMARY_INDEX_NAME, true);
157161
}
158162

159163
private void createSystemAliasViaV1Template(String indexName, String primaryIndexName) throws Exception {
@@ -265,12 +269,12 @@ public void testCreateSystemAliasViaComposableTemplateWithAllowsTemplates() thro
265269
);
266270
}
267271

268-
private void doCreateTest(Runnable runnable, String concreteIndex) {
272+
private void doCreateTest(Runnable runnable, String concreteIndex, boolean expandVectorDefault) {
269273
// Trigger the creation of the system index
270274
runnable.run();
271275
ensureGreen(INDEX_NAME);
272276

273-
assertMappingsAndSettings(TestSystemIndexDescriptor.getOldMappings(), concreteIndex);
277+
assertMappingsAndSettings(TestSystemIndexDescriptor.getOldMappings(expandVectorDefault), concreteIndex);
274278

275279
// Remove the index and alias...
276280
assertAcked(indicesAdmin().prepareAliases(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT).removeAlias(concreteIndex, INDEX_NAME).get());
@@ -283,7 +287,7 @@ private void doCreateTest(Runnable runnable, String concreteIndex) {
283287
runnable.run();
284288
ensureGreen(INDEX_NAME);
285289

286-
assertMappingsAndSettings(TestSystemIndexDescriptor.getNewMappings(), concreteIndex);
290+
assertMappingsAndSettings(TestSystemIndexDescriptor.getNewMappings(expandVectorDefault), concreteIndex);
287291
assertAliases(concreteIndex);
288292
}
289293

@@ -362,7 +366,7 @@ private void assertMappingsAndSettings(String expectedMappings, String concreteI
362366
);
363367
final Map<String, Object> sourceAsMap = mappings.get(concreteIndex).getSourceAsMap();
364368

365-
assertThat(sourceAsMap, equalTo(XContentHelper.convertToMap(XContentType.JSON.xContent(), expectedMappings, false)));
369+
assertThat(sourceAsMap, equalTo(XContentHelper.convertToMap(XContentType.JSON.xContent(), expectedMappings, true)));
366370

367371
final GetSettingsResponse getSettingsResponse = indicesAdmin().getSettings(
368372
new GetSettingsRequest(TEST_REQUEST_TIMEOUT).indices(INDEX_NAME)

server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ public MappingsVersion getMappingsVersion() {
9797
}
9898

9999
public static String getOldMappings() {
100+
return getOldMappings(false);
101+
}
102+
103+
public static String getOldMappings(boolean includeVectorDims) {
100104
try {
101105
final XContentBuilder builder = jsonBuilder();
102106

@@ -112,6 +116,18 @@ public static String getOldMappings() {
112116
builder.startObject("foo");
113117
builder.field("type", "text");
114118
builder.endObject();
119+
120+
builder.startObject("vector");
121+
builder.field("type", "dense_vector");
122+
if (includeVectorDims) {
123+
builder.field("dims", 3);
124+
}
125+
builder.field("index", true);
126+
builder.field("similarity", "cosine");
127+
builder.startObject("index_options");
128+
builder.field("type", "flat");
129+
builder.endObject();
130+
builder.endObject();
115131
}
116132
builder.endObject();
117133
}
@@ -124,6 +140,10 @@ public static String getOldMappings() {
124140
}
125141

126142
public static String getNewMappings() {
143+
return getNewMappings(false);
144+
}
145+
146+
public static String getNewMappings(boolean includeVectorDims) {
127147
try {
128148
final XContentBuilder builder = jsonBuilder();
129149

@@ -142,6 +162,18 @@ public static String getNewMappings() {
142162
builder.startObject("foo");
143163
builder.field("type", "text");
144164
builder.endObject();
165+
166+
builder.startObject("vector");
167+
builder.field("type", "dense_vector");
168+
if (includeVectorDims) {
169+
builder.field("dims", 3);
170+
}
171+
builder.field("index", true);
172+
builder.field("similarity", "cosine");
173+
builder.startObject("index_options");
174+
builder.field("type", "flat");
175+
builder.endObject();
176+
builder.endObject();
145177
}
146178
builder.endObject();
147179
}

server/src/main/java/org/elasticsearch/cluster/action/index/MappingUpdatedAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ protected void sendUpdateMapping(Index index, Mapping mappingUpdate, ActionListe
111111
putMappingRequest.source(mappingUpdate.toString(), XContentType.JSON);
112112
putMappingRequest.masterNodeTimeout(dynamicMappingUpdateTimeout);
113113
putMappingRequest.ackTimeout(TimeValue.ZERO);
114+
putMappingRequest.origin("bulk");
114115
client.execute(
115116
TransportAutoPutMappingAction.TYPE,
116117
putMappingRequest,

0 commit comments

Comments
 (0)