Skip to content

Commit 13946ea

Browse files
authored
Move flattened field to core. (elastic#70122)
This field mapper only lived in its own module so it could be licensed as x-pack basic. Now it can be moved to core, which matches its status as a core type. The PR also removes flattened fields from xpack usage stats now that they live in core. The usage stats were already removed in on master, but this PR was not backported to avoid a breaking change on 7.x. We have now clarified that usage stats updates are not considered breaking, so it is safe to backport this change.
1 parent 294c04d commit 13946ea

File tree

24 files changed

+212
-449
lines changed

24 files changed

+212
-449
lines changed

docs/reference/mapping/types/flattened.asciidoc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
[role="xpack"]
2-
[testenv="basic"]
3-
41
[[flattened]]
52
=== Flattened field type
63
++++

docs/reference/rest-api/info.asciidoc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,6 @@ Example response:
8686
"available" : true,
8787
"enabled" : true
8888
},
89-
"flattened" : {
90-
"available" : true,
91-
"enabled" : true
92-
},
9389
"frozen_indices" : {
9490
"available" : true,
9591
"enabled" : true

docs/reference/rest-api/usage.asciidoc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,6 @@ GET /_xpack/usage
284284
"available" : true,
285285
"enabled" : true
286286
},
287-
"flattened" : {
288-
"available" : true,
289-
"enabled" : true,
290-
"field_count" : 0
291-
},
292287
"vectors" : {
293288
"available" : true,
294289
"enabled" : true,

x-pack/plugin/src/test/resources/rest-api-spec/test/flattened/10_basic.yml renamed to rest-api-spec/src/main/resources/rest-api-spec/test/search/340_flattened.yml

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
---
2-
"Test exists query on flattened object field":
1+
setup:
32
- skip:
4-
version: " - 7.2.99"
5-
reason: "Flattened fields were implemented in 7.3."
3+
version: " - 7.12.99"
4+
reason: "Flattened fields were moved from xpack to core in 7.13."
65

6+
---
7+
"Test exists query on flattened object field":
78
- do:
89
indices.create:
910
index: flattened_test
@@ -53,10 +54,6 @@
5354

5455
---
5556
"Test query string query on flattened object field":
56-
- skip:
57-
version: " - 7.2.99"
58-
reason: "Flattened fields were implemented in 7.3."
59-
6057
- do:
6158
indices.create:
6259
index: test
@@ -113,10 +110,6 @@
113110

114111
---
115112
"Test fields option on flattened object field":
116-
- skip:
117-
version: " - 7.10.99"
118-
reason: "Fields option on search request was added in 7.10"
119-
120113
- do:
121114
indices.create:
122115
index: test
@@ -159,9 +152,6 @@
159152

160153
---
161154
"Test fields option on flattened object field with include_unmapped":
162-
- skip:
163-
version: ' - 7.10.99'
164-
reason: support was introduced in 7.11
165155
- do:
166156
indices.create:
167157
index: test

server/src/main/java/org/elasticsearch/index/mapper/DynamicKeyFieldMapper.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@
2525
* sure to passes an empty multi-fields list to help prevent conflicting sub-keys from being
2626
* registered.
2727
*
28-
* Note: we anticipate that 'flattened' fields will be the only implementation of this
29-
* interface. Flattened object fields live in the 'mapper-flattened' module.
28+
* Note: currently 'flattened' fields are the only implementation of this interface.
3029
*/
3130
public abstract class DynamicKeyFieldMapper extends FieldMapper {
3231

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/*
22
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
33
* or more contributor license agreements. Licensed under the Elastic License
4-
* 2.0; you may not use this file except in compliance with the Elastic License
5-
* 2.0.
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
67
*/
78

8-
package org.elasticsearch.xpack.flattened.mapper;
9+
package org.elasticsearch.index.mapper.flattened;
910

1011
import org.apache.lucene.index.DirectoryReader;
1112
import org.apache.lucene.index.LeafReaderContext;
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/*
22
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
33
* or more contributor license agreements. Licensed under the Elastic License
4-
* 2.0; you may not use this file except in compliance with the Elastic License
5-
* 2.0.
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
67
*/
78

8-
package org.elasticsearch.xpack.flattened.mapper;
9+
package org.elasticsearch.index.mapper.flattened;
910

1011
import org.apache.lucene.document.Field;
1112
import org.apache.lucene.document.SortedSetDocValuesField;
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/*
22
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
33
* or more contributor license agreements. Licensed under the Elastic License
4-
* 2.0; you may not use this file except in compliance with the Elastic License
5-
* 2.0.
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
67
*/
78

8-
package org.elasticsearch.xpack.flattened.mapper;
9+
package org.elasticsearch.index.mapper.flattened;
910

1011
import org.apache.lucene.index.DocValues;
1112
import org.apache.lucene.index.SortedSetDocValues;

server/src/main/java/org/elasticsearch/indices/IndicesModule.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.elasticsearch.index.mapper.TextFieldMapper;
4646
import org.elasticsearch.index.mapper.TypeFieldMapper;
4747
import org.elasticsearch.index.mapper.VersionFieldMapper;
48+
import org.elasticsearch.index.mapper.flattened.FlattenedFieldMapper;
4849
import org.elasticsearch.index.seqno.RetentionLeaseBackgroundSyncAction;
4950
import org.elasticsearch.index.seqno.RetentionLeaseSyncAction;
5051
import org.elasticsearch.index.seqno.RetentionLeaseSyncer;
@@ -123,18 +124,21 @@ public static Map<String, Mapper.TypeParser> getMappers(List<MapperPlugin> mappe
123124
}
124125
mappers.put(BooleanFieldMapper.CONTENT_TYPE, BooleanFieldMapper.PARSER);
125126
mappers.put(BinaryFieldMapper.CONTENT_TYPE, BinaryFieldMapper.PARSER);
127+
mappers.put(CompletionFieldMapper.CONTENT_TYPE, CompletionFieldMapper.PARSER);
128+
126129
DateFieldMapper.Resolution milliseconds = DateFieldMapper.Resolution.MILLISECONDS;
127130
mappers.put(milliseconds.type(), DateFieldMapper.MILLIS_PARSER);
128131
DateFieldMapper.Resolution nanoseconds = DateFieldMapper.Resolution.NANOSECONDS;
129132
mappers.put(nanoseconds.type(), DateFieldMapper.NANOS_PARSER);
133+
134+
mappers.put(FieldAliasMapper.CONTENT_TYPE, new FieldAliasMapper.TypeParser());
135+
mappers.put(FlattenedFieldMapper.CONTENT_TYPE, FlattenedFieldMapper.PARSER);
136+
mappers.put(GeoPointFieldMapper.CONTENT_TYPE, GeoPointFieldMapper.PARSER);
130137
mappers.put(IpFieldMapper.CONTENT_TYPE, IpFieldMapper.PARSER);
131-
mappers.put(TextFieldMapper.CONTENT_TYPE, TextFieldMapper.PARSER);
132138
mappers.put(KeywordFieldMapper.CONTENT_TYPE, KeywordFieldMapper.PARSER);
133139
mappers.put(ObjectMapper.CONTENT_TYPE, new ObjectMapper.TypeParser());
134140
mappers.put(ObjectMapper.NESTED_CONTENT_TYPE, new ObjectMapper.TypeParser());
135-
mappers.put(CompletionFieldMapper.CONTENT_TYPE, CompletionFieldMapper.PARSER);
136-
mappers.put(FieldAliasMapper.CONTENT_TYPE, new FieldAliasMapper.TypeParser());
137-
mappers.put(GeoPointFieldMapper.CONTENT_TYPE, GeoPointFieldMapper.PARSER);
141+
mappers.put(TextFieldMapper.CONTENT_TYPE, TextFieldMapper.PARSER);
138142

139143
for (MapperPlugin mapperPlugin : mapperPlugins) {
140144
for (Map.Entry<String, Mapper.TypeParser> entry : mapperPlugin.getMappers().entrySet()) {

server/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,22 @@
1111
import org.elasticsearch.common.collect.List;
1212
import org.elasticsearch.common.collect.Set;
1313
import org.elasticsearch.index.mapper.TypeFieldMapper.TypeFieldType;
14+
import org.elasticsearch.index.mapper.flattened.FlattenedFieldMapper;
1415
import org.elasticsearch.test.ESTestCase;
16+
import org.hamcrest.Matchers;
1517

1618
import java.util.Arrays;
1719
import java.util.Collection;
1820
import java.util.Collections;
21+
import java.util.HashMap;
22+
import java.util.HashSet;
23+
import java.util.Map;
1924

2025
import static java.util.Collections.emptyList;
2126
import static java.util.Collections.singletonList;
2227
import static org.hamcrest.CoreMatchers.instanceOf;
2328
import static org.hamcrest.Matchers.equalTo;
29+
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
2430

2531
public class FieldTypeLookupTests extends ESTestCase {
2632

@@ -218,4 +224,106 @@ private static int size(Iterable<MappedFieldType> iterable) {
218224
}
219225
return count;
220226
}
227+
228+
public void testFlattenedLookup() {
229+
String fieldName = "object1.object2.field";
230+
FlattenedFieldMapper mapper = createFlattenedMapper(fieldName);
231+
232+
FieldTypeLookup lookup = new FieldTypeLookup("_doc", singletonList(mapper), emptyList(), emptyList());
233+
assertEquals(mapper.fieldType(), lookup.get(fieldName));
234+
235+
String objectKey = "key1.key2";
236+
String searchFieldName = fieldName + "." + objectKey;
237+
238+
MappedFieldType searchFieldType = lookup.get(searchFieldName);
239+
assertEquals(mapper.keyedFieldName(), searchFieldType.name());
240+
assertThat(searchFieldType, Matchers.instanceOf(FlattenedFieldMapper.KeyedFlattenedFieldType.class));
241+
242+
FlattenedFieldMapper.KeyedFlattenedFieldType keyedFieldType = (FlattenedFieldMapper.KeyedFlattenedFieldType) searchFieldType;
243+
assertEquals(objectKey, keyedFieldType.key());
244+
}
245+
246+
public void testFlattenedLookupWithAlias() {
247+
String fieldName = "object1.object2.field";
248+
FlattenedFieldMapper mapper = createFlattenedMapper(fieldName);
249+
250+
String aliasName = "alias";
251+
FieldAliasMapper alias = new FieldAliasMapper(aliasName, aliasName, fieldName);
252+
253+
FieldTypeLookup lookup = new FieldTypeLookup("_doc", singletonList(mapper), singletonList(alias), emptyList());
254+
assertEquals(mapper.fieldType(), lookup.get(aliasName));
255+
256+
String objectKey = "key1.key2";
257+
String searchFieldName = aliasName + "." + objectKey;
258+
259+
MappedFieldType searchFieldType = lookup.get(searchFieldName);
260+
assertEquals(mapper.keyedFieldName(), searchFieldType.name());
261+
assertThat(searchFieldType, Matchers.instanceOf(FlattenedFieldMapper.KeyedFlattenedFieldType.class));
262+
263+
FlattenedFieldMapper.KeyedFlattenedFieldType keyedFieldType = (FlattenedFieldMapper.KeyedFlattenedFieldType) searchFieldType;
264+
assertEquals(objectKey, keyedFieldType.key());
265+
}
266+
267+
public void testFlattenedLookupWithMultipleFields() {
268+
String field1 = "object1.object2.field";
269+
String field2 = "object1.field";
270+
String field3 = "object2.field";
271+
272+
FlattenedFieldMapper mapper1 = createFlattenedMapper(field1);
273+
FlattenedFieldMapper mapper2 = createFlattenedMapper(field2);
274+
FlattenedFieldMapper mapper3 = createFlattenedMapper(field3);
275+
276+
FieldTypeLookup lookup = new FieldTypeLookup("_doc", Arrays.asList(mapper1, mapper2), emptyList(), emptyList());
277+
assertNotNull(lookup.get(field1 + ".some.key"));
278+
assertNotNull(lookup.get(field2 + ".some.key"));
279+
280+
lookup = new FieldTypeLookup("_doc", Arrays.asList(mapper1, mapper2, mapper3), emptyList(), emptyList());
281+
assertNotNull(lookup.get(field1 + ".some.key"));
282+
assertNotNull(lookup.get(field2 + ".some.key"));
283+
assertNotNull(lookup.get(field3 + ".some.key"));
284+
}
285+
286+
public void testMaxDynamicKeyDepth() {
287+
Map<String, DynamicKeyFieldMapper> mappers = new HashMap<>();
288+
Map<String, String> aliases = new HashMap<>();
289+
assertEquals(0, DynamicKeyFieldTypeLookup.getMaxKeyDepth(mappers, aliases));
290+
291+
// Add a flattened object field.
292+
String name = "object1.object2.field";
293+
FlattenedFieldMapper flattenedMapper = createFlattenedMapper(name);
294+
mappers.put(name, flattenedMapper);
295+
assertEquals(3, DynamicKeyFieldTypeLookup.getMaxKeyDepth(mappers, aliases));
296+
297+
// Add a short alias to that field.
298+
String aliasName = "alias";
299+
aliases.put(aliasName, name);
300+
assertEquals(3, DynamicKeyFieldTypeLookup.getMaxKeyDepth(mappers, aliases));
301+
302+
// Add a longer alias to that field.
303+
String longAliasName = "object1.object2.object3.alias";
304+
aliases.put(longAliasName, name);
305+
assertEquals(4, DynamicKeyFieldTypeLookup.getMaxKeyDepth(mappers, aliases));
306+
307+
// Update the long alias to refer to a non-flattened object field.
308+
String fieldName = "field";
309+
aliases.put(longAliasName, fieldName);
310+
assertEquals(3, DynamicKeyFieldTypeLookup.getMaxKeyDepth(mappers, aliases));
311+
}
312+
313+
public void testFieldLookupIterator() {
314+
MockFieldMapper mapper = new MockFieldMapper("foo");
315+
FlattenedFieldMapper flattenedMapper = createFlattenedMapper("object1.object2.field");
316+
317+
FieldTypeLookup lookup = new FieldTypeLookup("_doc", Arrays.asList(mapper, flattenedMapper), emptyList(), emptyList());
318+
319+
Collection<String> fieldNames = new HashSet<String>();
320+
lookup.filter(ft -> true).forEach(ft -> fieldNames.add(ft.name()));
321+
322+
assertThat(fieldNames, containsInAnyOrder(
323+
mapper.name(), flattenedMapper.name(), flattenedMapper.keyedFieldName()));
324+
}
325+
326+
private FlattenedFieldMapper createFlattenedMapper(String fieldName) {
327+
return new FlattenedFieldMapper.Builder(fieldName).build(new ContentPath());
328+
}
221329
}

0 commit comments

Comments
 (0)