24
24
import org .elasticsearch .common .regex .Regex ;
25
25
26
26
import java .util .Collection ;
27
+ import java .util .HashMap ;
27
28
import java .util .HashSet ;
28
29
import java .util .Iterator ;
29
30
import java .util .Map ;
@@ -37,31 +38,21 @@ class FieldTypeLookup implements Iterable<MappedFieldType> {
37
38
38
39
final CopyOnWriteHashMap <String , MappedFieldType > fullNameToFieldType ;
39
40
private final CopyOnWriteHashMap <String , String > aliasToConcreteName ;
41
+ private final DynamicKeyFieldTypeLookup dynamicKeyLookup ;
40
42
41
- private final CopyOnWriteHashMap <String , DynamicKeyFieldMapper > dynamicKeyMappers ;
42
-
43
- /**
44
- * The maximum field depth of any mapper that implements {@link DynamicKeyFieldMapper}.
45
- * Allows us stop searching for a 'dynamic key' mapper as soon as we've passed the maximum
46
- * possible field depth.
47
- */
48
- private final int maxDynamicKeyDepth ;
49
43
50
44
FieldTypeLookup () {
51
45
fullNameToFieldType = new CopyOnWriteHashMap <>();
52
46
aliasToConcreteName = new CopyOnWriteHashMap <>();
53
- dynamicKeyMappers = new CopyOnWriteHashMap <>();
54
- maxDynamicKeyDepth = 0 ;
47
+ dynamicKeyLookup = new DynamicKeyFieldTypeLookup ();
55
48
}
56
49
57
50
private FieldTypeLookup (CopyOnWriteHashMap <String , MappedFieldType > fullNameToFieldType ,
58
51
CopyOnWriteHashMap <String , String > aliasToConcreteName ,
59
- CopyOnWriteHashMap <String , DynamicKeyFieldMapper > dynamicKeyMappers ,
60
- int maxDynamicKeyDepth ) {
52
+ DynamicKeyFieldTypeLookup dynamicKeyLookup ) {
61
53
this .fullNameToFieldType = fullNameToFieldType ;
62
54
this .aliasToConcreteName = aliasToConcreteName ;
63
- this .dynamicKeyMappers = dynamicKeyMappers ;
64
- this .maxDynamicKeyDepth = maxDynamicKeyDepth ;
55
+ this .dynamicKeyLookup = dynamicKeyLookup ;
65
56
}
66
57
67
58
/**
@@ -80,7 +71,7 @@ public FieldTypeLookup copyAndAddAll(String type,
80
71
81
72
CopyOnWriteHashMap <String , MappedFieldType > fullName = this .fullNameToFieldType ;
82
73
CopyOnWriteHashMap <String , String > aliases = this .aliasToConcreteName ;
83
- CopyOnWriteHashMap <String , DynamicKeyFieldMapper > dynamicKeyMappers = this . dynamicKeyMappers ;
74
+ Map <String , DynamicKeyFieldMapper > dynamicKeyMappers = new HashMap <>() ;
84
75
85
76
for (FieldMapper fieldMapper : fieldMappers ) {
86
77
String fieldName = fieldMapper .name ();
@@ -92,8 +83,7 @@ public FieldTypeLookup copyAndAddAll(String type,
92
83
}
93
84
94
85
if (fieldMapper instanceof DynamicKeyFieldMapper ) {
95
- DynamicKeyFieldMapper dynamicKeyMapper = (DynamicKeyFieldMapper ) fieldMapper ;
96
- dynamicKeyMappers = dynamicKeyMappers .copyAndPut (fieldName , dynamicKeyMapper );
86
+ dynamicKeyMappers .put (fieldName , (DynamicKeyFieldMapper ) fieldMapper );
97
87
}
98
88
}
99
89
@@ -103,46 +93,8 @@ public FieldTypeLookup copyAndAddAll(String type,
103
93
aliases = aliases .copyAndPut (aliasName , path );
104
94
}
105
95
106
- int maxDynamicKeyDepth = getMaxDynamicKeyDepth (aliases , dynamicKeyMappers );
107
-
108
- return new FieldTypeLookup (fullName , aliases , dynamicKeyMappers , maxDynamicKeyDepth );
109
- }
110
-
111
- private static int getMaxDynamicKeyDepth (CopyOnWriteHashMap <String , String > aliases ,
112
- CopyOnWriteHashMap <String , DynamicKeyFieldMapper > dynamicKeyMappers ) {
113
- int maxFieldDepth = 0 ;
114
- for (Map .Entry <String , String > entry : aliases .entrySet ()) {
115
- String aliasName = entry .getKey ();
116
- String path = entry .getValue ();
117
- if (dynamicKeyMappers .containsKey (path )) {
118
- maxFieldDepth = Math .max (maxFieldDepth , fieldDepth (aliasName ));
119
- }
120
- }
121
-
122
- for (String fieldName : dynamicKeyMappers .keySet ()) {
123
- if (dynamicKeyMappers .containsKey (fieldName )) {
124
- maxFieldDepth = Math .max (maxFieldDepth , fieldDepth (fieldName ));
125
- }
126
- }
127
-
128
- return maxFieldDepth ;
129
- }
130
-
131
- /**
132
- * Computes the total depth of this field by counting the number of parent fields
133
- * in its path. As an example, the field 'parent1.parent2.field' has depth 3.
134
- */
135
- private static int fieldDepth (String field ) {
136
- int numDots = 0 ;
137
- int dotIndex = -1 ;
138
- while (true ) {
139
- dotIndex = field .indexOf ('.' , dotIndex + 1 );
140
- if (dotIndex < 0 ) {
141
- break ;
142
- }
143
- numDots ++;
144
- }
145
- return numDots + 1 ;
96
+ DynamicKeyFieldTypeLookup newDynamicKeyLookup = this .dynamicKeyLookup .copyAndAddAll (dynamicKeyMappers , aliases );
97
+ return new FieldTypeLookup (fullName , aliases , newDynamicKeyLookup );
146
98
}
147
99
148
100
/**
@@ -157,37 +109,7 @@ public MappedFieldType get(String field) {
157
109
158
110
// If the mapping contains fields that support dynamic sub-key lookup, check
159
111
// if this could correspond to a keyed field of the form 'path_to_field.path_to_key'.
160
- return !dynamicKeyMappers .isEmpty () ? getKeyedFieldType (field ) : null ;
161
- }
162
-
163
- /**
164
- * Check if the given field corresponds to a dynamic lookup mapper of the
165
- * form 'path_to_field.path_to_key'. If so, returns a field type that
166
- * can be used to perform searches on this field.
167
- */
168
- private MappedFieldType getKeyedFieldType (String field ) {
169
- int dotIndex = -1 ;
170
- int fieldDepth = 0 ;
171
-
172
- while (true ) {
173
- if (++fieldDepth > maxDynamicKeyDepth ) {
174
- return null ;
175
- }
176
-
177
- dotIndex = field .indexOf ('.' , dotIndex + 1 );
178
- if (dotIndex < 0 ) {
179
- return null ;
180
- }
181
-
182
- String parentField = field .substring (0 , dotIndex );
183
- String concreteField = aliasToConcreteName .getOrDefault (parentField , parentField );
184
- DynamicKeyFieldMapper mapper = dynamicKeyMappers .get (concreteField );
185
-
186
- if (mapper != null ) {
187
- String key = field .substring (dotIndex + 1 );
188
- return mapper .keyedFieldType (key );
189
- }
190
- }
112
+ return dynamicKeyLookup .get (field );
191
113
}
192
114
193
115
/**
@@ -211,19 +133,7 @@ public Set<String> simpleMatchToFullName(String pattern) {
211
133
@ Override
212
134
public Iterator <MappedFieldType > iterator () {
213
135
Iterator <MappedFieldType > concreteFieldTypes = fullNameToFieldType .values ().iterator ();
214
-
215
- if (dynamicKeyMappers .isEmpty ()) {
216
- return concreteFieldTypes ;
217
- } else {
218
- Iterator <MappedFieldType > keyedFieldTypes = dynamicKeyMappers .values ().stream ()
219
- .<MappedFieldType >map (mapper -> mapper .keyedFieldType ("" ))
220
- .iterator ();
221
- return Iterators .concat (concreteFieldTypes , keyedFieldTypes );
222
- }
223
- }
224
-
225
- // Visible for testing.
226
- int maxKeyedLookupDepth () {
227
- return maxDynamicKeyDepth ;
136
+ Iterator <MappedFieldType > keyedFieldTypes = dynamicKeyLookup .fieldTypes ();
137
+ return Iterators .concat (concreteFieldTypes , keyedFieldTypes );
228
138
}
229
139
}
0 commit comments