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

_score should not be a reserved attribute in ES|QL #118435

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
6 changes: 6 additions & 0 deletions docs/changelog/118435.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 118435
summary: '`_score` should not be a reserved attribute in ES|QL'
area: ES|QL
type: enhancement
issues:
- 118460
6 changes: 6 additions & 0 deletions muted-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ tests:
- class: "org.elasticsearch.xpack.esql.qa.mixed.MixedClusterEsqlSpecIT"
method: "test {scoring.*}"
issue: https://github.com/elastic/elasticsearch/issues/117641
- class: "org.elasticsearch.xpack.esql.qa.mixed.MultilusterEsqlSpecIT"
method: "test {scoring.*}"
issue: https://github.com/elastic/elasticsearch/issues/118460
- class: "org.elasticsearch.xpack.esql.ccq.MultiClusterSpecIT"
method: "test {scoring.*}"
issue: https://github.com/elastic/elasticsearch/issues/118460
- class: org.elasticsearch.xpack.esql.ccq.MultiClusterSpecIT
method: test {scoring.QstrWithFieldAndScoringSortedEval}
issue: https://github.com/elastic/elasticsearch/issues/117751
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,33 @@ book_no:keyword | c_score:double
7350 | 2.0
7140 | 3.0
;

QstrScoreManipulation
required_capability: metadata_score
required_capability: qstr_function

from books metadata _score
| where qstr("title:rings")
| eval _score = _score + 1
| keep book_no, title, _score
| limit 2;

book_no:keyword | title:text | _score:double
4023 | A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings | 2.6404519081115723
2714 | Return of the King Being the Third Part of The Lord of the Rings | 2.9239964485168457
;

QstrScoreOverride
required_capability: metadata_score
required_capability: qstr_function

from books metadata _score
| where qstr("title:rings")
| eval _score = "foobar"
| keep book_no, title, _score
| limit 2;

book_no:keyword | title:text | _score:keyword
4023 | A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings | foobar
2714 | Return of the King Being the Third Part of The Lord of the Rings | foobar
;
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.elasticsearch.xpack.esql.core.expression.Expression;
import org.elasticsearch.xpack.esql.core.expression.Expressions;
import org.elasticsearch.xpack.esql.core.expression.FieldAttribute;
import org.elasticsearch.xpack.esql.core.expression.MetadataAttribute;
import org.elasticsearch.xpack.esql.core.expression.NamedExpression;
import org.elasticsearch.xpack.esql.core.expression.TypeResolutions;
import org.elasticsearch.xpack.esql.core.expression.function.Function;
Expand Down Expand Up @@ -208,7 +207,6 @@ else if (p instanceof Lookup lookup) {
checkJoin(p, failures);
});
checkRemoteEnrich(plan, failures);
checkMetadataScoreNameReserved(plan, failures);

if (failures.isEmpty()) {
checkLicense(plan, licenseState, failures);
Expand All @@ -222,13 +220,6 @@ else if (p instanceof Lookup lookup) {
return failures;
}

private static void checkMetadataScoreNameReserved(LogicalPlan p, Set<Failure> failures) {
// _score can only be set as metadata attribute
if (p.inputSet().stream().anyMatch(a -> MetadataAttribute.SCORE.equals(a.name()) && (a instanceof MetadataAttribute) == false)) {
failures.add(fail(p, "`" + MetadataAttribute.SCORE + "` is a reserved METADATA attribute"));
}
}

private void checkSort(LogicalPlan p, Set<Failure> failures) {
if (p instanceof OrderBy ob) {
ob.order().forEach(o -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.esql.VerificationException;
import org.elasticsearch.xpack.esql.action.EsqlCapabilities;
import org.elasticsearch.xpack.esql.core.expression.Attribute;
import org.elasticsearch.xpack.esql.core.type.DataType;
import org.elasticsearch.xpack.esql.core.type.EsField;
import org.elasticsearch.xpack.esql.core.type.InvalidMappedField;
Expand All @@ -22,7 +21,6 @@
import org.elasticsearch.xpack.esql.parser.EsqlParser;
import org.elasticsearch.xpack.esql.parser.QueryParam;
import org.elasticsearch.xpack.esql.parser.QueryParams;
import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan;

import java.util.ArrayList;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -1805,29 +1803,6 @@ public void testToDatePeriodToTimeDurationWithInvalidType() {
);
}

public void testNonMetadataScore() {
assumeTrue("'METADATA _score' is disabled", EsqlCapabilities.Cap.METADATA_SCORE.isEnabled());
assertEquals("1:12: `_score` is a reserved METADATA attribute", error("from foo | eval _score = 10"));

assertEquals(
"1:48: `_score` is a reserved METADATA attribute",
error("from foo metadata _score | where qstr(\"bar\") | eval _score = _score + 1")
);
}

public void testScoreRenaming() {
assumeTrue("'METADATA _score' is disabled", EsqlCapabilities.Cap.METADATA_SCORE.isEnabled());
assertEquals("1:33: `_score` is a reserved METADATA attribute", error("from foo METADATA _id, _score | rename _id as _score"));

assertTrue(passes("from foo metadata _score | rename _score as foo").stream().anyMatch(a -> a.name().equals("foo")));
}

private List<Attribute> passes(String query) {
LogicalPlan logicalPlan = defaultAnalyzer.analyze(parser.createStatement(query));
assertTrue(logicalPlan.resolved());
return logicalPlan.output();
}

public void testIntervalAsString() {
// DateTrunc
for (String interval : List.of("1 minu", "1 dy", "1.5 minutes", "0.5 days", "minutes 1", "day 5")) {
Expand Down