Skip to content

Commit 7b79a52

Browse files
authored
Allow missing semantic text field in bulk updates (#116478)
This update enables bulk update operations to succeed even if the semantic text field is absent in the partial update. For the simple case where the field isn’t referenced by a copy_to operation from another source, the inference can be safely bypassed, allowing the update to proceed without errors.
1 parent f88a004 commit 7b79a52

File tree

5 files changed

+69
-2
lines changed

5 files changed

+69
-2
lines changed

docs/changelog/116478.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 116478
2+
summary: Semantic text simple partial update
3+
area: Search
4+
type: bug
5+
issues: []

x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/InferenceFeatures.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ public Set<NodeFeature> getFeatures() {
3838

3939
@Override
4040
public Set<NodeFeature> getTestFeatures() {
41-
return Set.of(SemanticTextFieldMapper.SEMANTIC_TEXT_IN_OBJECT_FIELD_FIX);
41+
return Set.of(
42+
SemanticTextFieldMapper.SEMANTIC_TEXT_IN_OBJECT_FIELD_FIX,
43+
SemanticTextFieldMapper.SEMANTIC_TEXT_SINGLE_FIELD_UPDATE_FIX
44+
);
4245
}
4346
}

x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/action/filter/ShardBulkInferenceActionFilter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ private Map<String, List<FieldInferenceRequest>> createFieldInferenceRequests(Bu
446446
String field = entry.getName();
447447
String inferenceId = entry.getInferenceId();
448448
var originalFieldValue = XContentMapValues.extractValue(field, docMap);
449-
if (originalFieldValue instanceof Map) {
449+
if (originalFieldValue instanceof Map || (originalFieldValue == null && entry.getSourceFields().length == 1)) {
450+
// Inference has already been computed, or there is no inference required.
450451
continue;
451452
}
452453
int order = 0;

x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/mapper/SemanticTextFieldMapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ public class SemanticTextFieldMapper extends FieldMapper implements InferenceFie
9191
public static final NodeFeature SEMANTIC_TEXT_DEFAULT_ELSER_2 = new NodeFeature("semantic_text.default_elser_2");
9292
public static final NodeFeature SEMANTIC_TEXT_IN_OBJECT_FIELD_FIX = new NodeFeature("semantic_text.in_object_field_fix");
9393

94+
public static final NodeFeature SEMANTIC_TEXT_SINGLE_FIELD_UPDATE_FIX = new NodeFeature("semantic_text.single_field_update_fix");
95+
9496
public static final String CONTENT_TYPE = "semantic_text";
9597
public static final String DEFAULT_ELSER_2_INFERENCE_ID = DEFAULT_ELSER_ID;
9698

x-pack/plugin/inference/src/yamlRestTest/resources/rest-api-spec/test/inference/60_semantic_text_inference_update.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,3 +610,59 @@ setup:
610610
- exists: _source.dense_field.inference.chunks.0.embeddings
611611
- match: { _source.dense_field.inference.chunks.0.text: "another updated inference test" }
612612
- match: { _source.non_inference_field: "updated non inference test" }
613+
614+
---
615+
"Bypass inference on bulk update operation":
616+
- requires:
617+
cluster_features: semantic_text.single_field_update_fix
618+
reason: Standalone semantic text fields are now optional in a bulk update operation
619+
620+
# Update as upsert
621+
- do:
622+
bulk:
623+
body:
624+
- '{"update": {"_index": "test-index", "_id": "doc_1"}}'
625+
- '{"doc": { "sparse_field": "inference test", "dense_field": "another inference test", "non_inference_field": "non inference test" }, "doc_as_upsert": true}'
626+
627+
- match: { errors: false }
628+
- match: { items.0.update.result: "created" }
629+
630+
- do:
631+
bulk:
632+
body:
633+
- '{"update": {"_index": "test-index", "_id": "doc_1"}}'
634+
- '{"doc": { "non_inference_field": "another value" }, "doc_as_upsert": true}'
635+
636+
- match: { errors: false }
637+
- match: { items.0.update.result: "updated" }
638+
639+
- do:
640+
get:
641+
index: test-index
642+
id: doc_1
643+
644+
- match: { _source.sparse_field.text: "inference test" }
645+
- exists: _source.sparse_field.inference.chunks.0.embeddings
646+
- match: { _source.sparse_field.inference.chunks.0.text: "inference test" }
647+
- match: { _source.dense_field.text: "another inference test" }
648+
- exists: _source.dense_field.inference.chunks.0.embeddings
649+
- match: { _source.dense_field.inference.chunks.0.text: "another inference test" }
650+
- match: { _source.non_inference_field: "another value" }
651+
652+
- do:
653+
bulk:
654+
body:
655+
- '{"update": {"_index": "test-index", "_id": "doc_1"}}'
656+
- '{"doc": { "sparse_field": null, "dense_field": null, "non_inference_field": "updated value" }, "doc_as_upsert": true}'
657+
658+
- match: { errors: false }
659+
- match: { items.0.update.result: "updated" }
660+
661+
- do:
662+
get:
663+
index: test-index
664+
id: doc_1
665+
666+
- match: { _source.sparse_field: null }
667+
- match: { _source.dense_field: null }
668+
- match: { _source.non_inference_field: "updated value" }

0 commit comments

Comments
 (0)