diff --git a/docs/changelog/127229.yaml b/docs/changelog/127229.yaml new file mode 100644 index 0000000000000..fe551c95c6d01 --- /dev/null +++ b/docs/changelog/127229.yaml @@ -0,0 +1,6 @@ +pr: 127229 +summary: Return BAD_REQUEST when a field scorer references a missing field +area: Ranking +type: bug +issues: + - 127162 diff --git a/plugins/examples/rescore/src/yamlRestTest/resources/rest-api-spec/test/example-rescore/30_factor_field.yml b/plugins/examples/rescore/src/yamlRestTest/resources/rest-api-spec/test/example-rescore/30_factor_field.yml index 6c39fd0b0922b..110801b235cf2 100644 --- a/plugins/examples/rescore/src/yamlRestTest/resources/rest-api-spec/test/example-rescore/30_factor_field.yml +++ b/plugins/examples/rescore/src/yamlRestTest/resources/rest-api-spec/test/example-rescore/30_factor_field.yml @@ -48,6 +48,24 @@ setup: - match: { hits.hits.1._score: 20 } - match: { hits.hits.2._score: 10 } +--- +"referencing a missing field returns bad request": + - requires: + cluster_features: [ "search.rescorer.missing.field.bad.request" ] + reason: "Testing the behaviour change with this feature" + - do: + catch: bad_request + search: + index: test + body: + rescore: + example: + factor: 1 + factor_field: missing + - match: { status: 400 } + - match: { error.root_cause.0.type: "illegal_argument_exception" } + - match: { error.root_cause.0.reason: "Missing value for field [missing]" } + --- "sorted based on a numeric field and rescored based on a factor field using a window size": - do: diff --git a/server/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java b/server/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java index 52767f3ae2967..4a1f59c71e361 100644 --- a/server/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java +++ b/server/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java @@ -11,7 +11,6 @@ import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.Explanation; -import org.elasticsearch.ElasticsearchException; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; @@ -73,7 +72,7 @@ public double score(int docId, float subQueryScore) throws IOException { if (missing != null) { value = missing; } else { - throw new ElasticsearchException("Missing value for field [" + field + "]"); + throw new IllegalArgumentException("Missing value for field [" + field + "]"); } } double val = value * boostFactor; diff --git a/server/src/main/java/org/elasticsearch/search/SearchFeatures.java b/server/src/main/java/org/elasticsearch/search/SearchFeatures.java index 3970b6effe70c..6c835bdf8badc 100644 --- a/server/src/main/java/org/elasticsearch/search/SearchFeatures.java +++ b/server/src/main/java/org/elasticsearch/search/SearchFeatures.java @@ -28,9 +28,10 @@ public Set getFeatures() { public static final NodeFeature COMPLETION_FIELD_SUPPORTS_DUPLICATE_SUGGESTIONS = new NodeFeature( "search.completion_field.duplicate.support" ); + public static final NodeFeature RESCORER_MISSING_FIELD_BAD_REQUEST = new NodeFeature("search.rescorer.missing.field.bad.request"); @Override public Set getTestFeatures() { - return Set.of(RETRIEVER_RESCORER_ENABLED, COMPLETION_FIELD_SUPPORTS_DUPLICATE_SUGGESTIONS); + return Set.of(RETRIEVER_RESCORER_ENABLED, COMPLETION_FIELD_SUPPORTS_DUPLICATE_SUGGESTIONS, RESCORER_MISSING_FIELD_BAD_REQUEST); } }