Skip to content

Commit 3da738e

Browse files
authored
Support fetching _tier field value (#71379)
Now that the `fields` option allows fetching metadata fields, we can support loading the new `_tier` metadata field. Relates to #63569 and #68135.
1 parent 5baabff commit 3da738e

File tree

3 files changed

+53
-16
lines changed

3 files changed

+53
-16
lines changed

docs/reference/mapping/fields.asciidoc

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ fields can be customized when a mapping is created.
1313

1414
The index to which the document belongs.
1515

16-
<<mapping-tier-field,`_tier`>>::
17-
18-
The current data tier preference of the index to which the document belongs.
19-
20-
2116
<<mapping-id-field,`_id`>>::
2217

2318
The document's ID.
@@ -67,6 +62,10 @@ fields can be customized when a mapping is created.
6762

6863
Application specific metadata.
6964

65+
<<mapping-tier-field,`_tier`>>::
66+
67+
The current data tier preference of the index to which the document belongs.
68+
7069
include::fields/doc-count-field.asciidoc[]
7170

7271
include::fields/field-names-field.asciidoc[]
@@ -77,10 +76,10 @@ include::fields/id-field.asciidoc[]
7776

7877
include::fields/index-field.asciidoc[]
7978

80-
include::fields/tier-field.asciidoc[]
81-
8279
include::fields/meta-field.asciidoc[]
8380

8481
include::fields/routing-field.asciidoc[]
8582

8683
include::fields/source-field.asciidoc[]
84+
85+
include::fields/tier-field.asciidoc[]

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/mapper/DataTierFieldMapper.java

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.apache.lucene.search.Query;
1313
import org.elasticsearch.common.Strings;
1414
import org.elasticsearch.common.regex.Regex;
15+
import org.elasticsearch.common.settings.Settings;
1516
import org.elasticsearch.index.mapper.ConstantFieldType;
1617
import org.elasticsearch.index.mapper.KeywordFieldMapper;
1718
import org.elasticsearch.index.mapper.MetadataFieldMapper;
@@ -20,6 +21,7 @@
2021
import org.elasticsearch.xpack.cluster.routing.allocation.DataTierAllocationDecider;
2122

2223
import java.util.Collections;
24+
import java.util.List;
2325

2426
public class DataTierFieldMapper extends MetadataFieldMapper {
2527

@@ -52,28 +54,50 @@ protected boolean matches(String pattern, boolean caseInsensitive, SearchExecuti
5254
if (caseInsensitive) {
5355
pattern = Strings.toLowercaseAscii(pattern);
5456
}
55-
String tierPreference = DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING.get(context.getIndexSettings().getSettings());
56-
if (Strings.hasText(tierPreference) == false) {
57+
58+
String tierPreference = getTierPreference(context);
59+
if (tierPreference == null) {
5760
return false;
5861
}
59-
// Tier preference can be a comma-delimited list of tiers, ordered by preference
60-
// It was decided we should only test the first of these potentially multiple preferences.
61-
String firstPreference = tierPreference.split(",")[0].trim();
62-
return Regex.simpleMatch(pattern, firstPreference);
62+
return Regex.simpleMatch(pattern, tierPreference);
6363
}
6464

6565
@Override
6666
public Query existsQuery(SearchExecutionContext context) {
67-
String tierPreference = DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING.get(context.getIndexSettings().getSettings());
68-
if (Strings.hasText(tierPreference) == false) {
67+
String tierPreference = getTierPreference(context);
68+
if (tierPreference == null) {
6969
return new MatchNoDocsQuery();
7070
}
7171
return new MatchAllDocsQuery();
7272
}
7373

7474
@Override
7575
public ValueFetcher valueFetcher(SearchExecutionContext context, String format) {
76-
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
76+
if (format != null) {
77+
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
78+
}
79+
80+
String tierPreference = getTierPreference(context);
81+
return tierPreference == null
82+
? lookup -> List.of()
83+
: lookup -> List.of(tierPreference);
84+
}
85+
86+
/**
87+
* Retrieve the first tier preference from the index setting. If the setting is not
88+
* present, then return null.
89+
*/
90+
private String getTierPreference(SearchExecutionContext context) {
91+
Settings settings = context.getIndexSettings().getSettings();
92+
String value = DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING.get(settings);
93+
94+
if (Strings.hasText(value) == false) {
95+
return null;
96+
}
97+
98+
// Tier preference can be a comma-delimited list of tiers, ordered by preference
99+
// It was decided we should only test the first of these potentially multiple preferences.
100+
return value.split(",")[0].trim();
77101
}
78102
}
79103

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/cluster/routing/allocation/mapper/DataTierFieldTypeTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,18 @@
1616
import org.elasticsearch.index.IndexSettings;
1717
import org.elasticsearch.index.mapper.MappedFieldType;
1818
import org.elasticsearch.index.mapper.MapperServiceTestCase;
19+
import org.elasticsearch.index.mapper.ValueFetcher;
1920
import org.elasticsearch.index.query.QueryShardException;
2021
import org.elasticsearch.index.query.SearchExecutionContext;
22+
import org.elasticsearch.search.lookup.SourceLookup;
2123
import org.elasticsearch.xpack.cluster.routing.allocation.DataTierAllocationDecider;
2224

2325
import java.io.IOException;
2426
import java.util.Arrays;
2527
import java.util.function.Predicate;
2628

2729
import static java.util.Collections.emptyMap;
30+
import static java.util.Collections.singletonList;
2831
import static org.hamcrest.Matchers.containsString;
2932

3033
public class DataTierFieldTypeTests extends MapperServiceTestCase {
@@ -81,6 +84,17 @@ public void testRegexpQuery() {
8184
assertThat(e.getMessage(), containsString("Can only use regexp queries on keyword and text fields"));
8285
}
8386

87+
public void testFetchValue() throws IOException {
88+
MappedFieldType ft = DataTierFieldMapper.DataTierFieldType.INSTANCE;
89+
SourceLookup lookup = new SourceLookup();
90+
91+
ValueFetcher valueFetcher = ft.valueFetcher(createContext(), null);
92+
assertEquals(singletonList("data_warm"), valueFetcher.fetchValues(lookup));
93+
94+
ValueFetcher emptyValueFetcher = ft.valueFetcher(createContextWithoutSetting(), null);
95+
assertTrue(emptyValueFetcher.fetchValues(lookup).isEmpty());
96+
}
97+
8498
private SearchExecutionContext createContext() {
8599
IndexMetadata indexMetadata = IndexMetadata.builder("index")
86100
.settings(

0 commit comments

Comments
 (0)