31
31
import org .elasticsearch .common .collect .Tuple ;
32
32
import org .elasticsearch .common .document .DocumentField ;
33
33
import org .elasticsearch .common .lucene .search .Queries ;
34
- import org .elasticsearch .common .regex .Regex ;
35
34
import org .elasticsearch .common .text .Text ;
36
35
import org .elasticsearch .common .xcontent .XContentHelper ;
37
36
import org .elasticsearch .common .xcontent .XContentType ;
55
54
import org .elasticsearch .tasks .TaskCancelledException ;
56
55
57
56
import java .io .IOException ;
58
- import java .util .ArrayList ;
57
+ import java .util .Collection ;
59
58
import java .util .Collections ;
60
59
import java .util .HashMap ;
61
60
import java .util .HashSet ;
@@ -84,8 +83,7 @@ public void preProcess(SearchContext context) {
84
83
@ Override
85
84
public void execute (SearchContext context ) {
86
85
final FieldsVisitor fieldsVisitor ;
87
- Set <String > fieldNames = null ;
88
- List <String > fieldNamePatterns = null ;
86
+ Map <String , Set <String >> storedToRequestedFields = new HashMap <>();
89
87
StoredFieldsContext storedFieldsContext = context .storedFieldsContext ();
90
88
91
89
if (storedFieldsContext == null ) {
@@ -98,39 +96,36 @@ public void execute(SearchContext context) {
98
96
// disable stored fields entirely
99
97
fieldsVisitor = null ;
100
98
} else {
101
- for (String fieldName : context .storedFieldsContext ().fieldNames ()) {
102
- if (fieldName .equals (SourceFieldMapper .NAME )) {
99
+ for (String fieldNameOrPattern : context .storedFieldsContext ().fieldNames ()) {
100
+ if (fieldNameOrPattern .equals (SourceFieldMapper .NAME )) {
103
101
FetchSourceContext fetchSourceContext = context .hasFetchSourceContext () ? context .fetchSourceContext ()
104
- : FetchSourceContext .FETCH_SOURCE ;
102
+ : FetchSourceContext .FETCH_SOURCE ;
105
103
context .fetchSourceContext (new FetchSourceContext (true , fetchSourceContext .includes (), fetchSourceContext .excludes ()));
106
104
continue ;
107
105
}
108
- if (Regex .isSimpleMatchPattern (fieldName )) {
109
- if (fieldNamePatterns == null ) {
110
- fieldNamePatterns = new ArrayList <>();
111
- }
112
- fieldNamePatterns .add (fieldName );
113
- } else {
106
+
107
+ Collection <String > fieldNames = context .mapperService ().simpleMatchToFullName (fieldNameOrPattern );
108
+ for (String fieldName : fieldNames ) {
114
109
MappedFieldType fieldType = context .smartNameFieldType (fieldName );
115
110
if (fieldType == null ) {
116
111
// Only fail if we know it is a object field, missing paths / fields shouldn't fail.
117
112
if (context .getObjectMapper (fieldName ) != null ) {
118
113
throw new IllegalArgumentException ("field [" + fieldName + "] isn't a leaf field" );
119
114
}
115
+ } else {
116
+ String storedField = fieldType .name ();
117
+ Set <String > requestedFields = storedToRequestedFields .computeIfAbsent (
118
+ storedField , key -> new HashSet <>());
119
+ requestedFields .add (fieldName );
120
120
}
121
- if (fieldNames == null ) {
122
- fieldNames = new HashSet <>();
123
- }
124
- fieldNames .add (fieldName );
125
121
}
126
122
}
127
123
boolean loadSource = context .sourceRequested ();
128
- if (fieldNames == null && fieldNamePatterns == null ) {
124
+ if (storedToRequestedFields . isEmpty () ) {
129
125
// empty list specified, default to disable _source if no explicit indication
130
126
fieldsVisitor = new FieldsVisitor (loadSource );
131
127
} else {
132
- fieldsVisitor = new CustomFieldsVisitor (fieldNames == null ? Collections .emptySet () : fieldNames ,
133
- fieldNamePatterns == null ? Collections .emptyList () : fieldNamePatterns , loadSource );
128
+ fieldsVisitor = new CustomFieldsVisitor (storedToRequestedFields .keySet (), loadSource );
134
129
}
135
130
}
136
131
@@ -149,10 +144,11 @@ public void execute(SearchContext context) {
149
144
final SearchHit searchHit ;
150
145
int rootDocId = findRootDocumentIfNested (context , subReaderContext , subDocId );
151
146
if (rootDocId != -1 ) {
152
- searchHit = createNestedSearchHit (context , docId , subDocId , rootDocId , fieldNames , fieldNamePatterns ,
153
- subReaderContext );
147
+ searchHit = createNestedSearchHit (context , docId , subDocId , rootDocId ,
148
+ storedToRequestedFields , subReaderContext );
154
149
} else {
155
- searchHit = createSearchHit (context , fieldsVisitor , docId , subDocId , subReaderContext );
150
+ searchHit = createSearchHit (context , fieldsVisitor , docId , subDocId ,
151
+ storedToRequestedFields , subReaderContext );
156
152
}
157
153
158
154
hits [index ] = searchHit ;
@@ -190,21 +186,18 @@ private int findRootDocumentIfNested(SearchContext context, LeafReaderContext su
190
186
return -1 ;
191
187
}
192
188
193
- private SearchHit createSearchHit (SearchContext context , FieldsVisitor fieldsVisitor , int docId , int subDocId ,
189
+ private SearchHit createSearchHit (SearchContext context ,
190
+ FieldsVisitor fieldsVisitor ,
191
+ int docId ,
192
+ int subDocId ,
193
+ Map <String , Set <String >> storedToRequestedFields ,
194
194
LeafReaderContext subReaderContext ) {
195
195
if (fieldsVisitor == null ) {
196
196
return new SearchHit (docId );
197
197
}
198
- loadStoredFields (context , subReaderContext , fieldsVisitor , subDocId );
199
- fieldsVisitor .postProcess (context .mapperService ());
200
198
201
- Map <String , DocumentField > searchFields = null ;
202
- if (!fieldsVisitor .fields ().isEmpty ()) {
203
- searchFields = new HashMap <>(fieldsVisitor .fields ().size ());
204
- for (Map .Entry <String , List <Object >> entry : fieldsVisitor .fields ().entrySet ()) {
205
- searchFields .put (entry .getKey (), new DocumentField (entry .getKey (), entry .getValue ()));
206
- }
207
- }
199
+ Map <String , DocumentField > searchFields = getSearchFields (context , fieldsVisitor , subDocId ,
200
+ storedToRequestedFields , subReaderContext );
208
201
209
202
DocumentMapper documentMapper = context .mapperService ().documentMapper (fieldsVisitor .uid ().type ());
210
203
Text typeText ;
@@ -223,9 +216,40 @@ private SearchHit createSearchHit(SearchContext context, FieldsVisitor fieldsVis
223
216
return searchHit ;
224
217
}
225
218
226
- private SearchHit createNestedSearchHit (SearchContext context , int nestedTopDocId , int nestedSubDocId ,
227
- int rootSubDocId , Set <String > fieldNames ,
228
- List <String > fieldNamePatterns , LeafReaderContext subReaderContext ) throws IOException {
219
+ private Map <String , DocumentField > getSearchFields (SearchContext context ,
220
+ FieldsVisitor fieldsVisitor ,
221
+ int subDocId ,
222
+ Map <String , Set <String >> storedToRequestedFields ,
223
+ LeafReaderContext subReaderContext ) {
224
+ loadStoredFields (context , subReaderContext , fieldsVisitor , subDocId );
225
+ fieldsVisitor .postProcess (context .mapperService ());
226
+
227
+ if (fieldsVisitor .fields ().isEmpty ()) {
228
+ return null ;
229
+ }
230
+
231
+ Map <String , DocumentField > searchFields = new HashMap <>(fieldsVisitor .fields ().size ());
232
+ for (Map .Entry <String , List <Object >> entry : fieldsVisitor .fields ().entrySet ()) {
233
+ String storedField = entry .getKey ();
234
+ List <Object > storedValues = entry .getValue ();
235
+
236
+ if (storedToRequestedFields .containsKey (storedField )) {
237
+ for (String requestedField : storedToRequestedFields .get (storedField )) {
238
+ searchFields .put (requestedField , new DocumentField (requestedField , storedValues ));
239
+ }
240
+ } else {
241
+ searchFields .put (storedField , new DocumentField (storedField , storedValues ));
242
+ }
243
+ }
244
+ return searchFields ;
245
+ }
246
+
247
+ private SearchHit createNestedSearchHit (SearchContext context ,
248
+ int nestedTopDocId ,
249
+ int nestedSubDocId ,
250
+ int rootSubDocId ,
251
+ Map <String , Set <String >> storedToRequestedFields ,
252
+ LeafReaderContext subReaderContext ) throws IOException {
229
253
// Also if highlighting is requested on nested documents we need to fetch the _source from the root document,
230
254
// otherwise highlighting will attempt to fetch the _source from the nested doc, which will fail,
231
255
// because the entire _source is only stored with the root document.
@@ -244,9 +268,13 @@ private SearchHit createNestedSearchHit(SearchContext context, int nestedTopDocI
244
268
source = null ;
245
269
}
246
270
271
+ Map <String , DocumentField > searchFields = null ;
272
+ if (context .hasStoredFields () && !context .storedFieldsContext ().fieldNames ().isEmpty ()) {
273
+ FieldsVisitor nestedFieldsVisitor = new CustomFieldsVisitor (storedToRequestedFields .keySet (), false );
274
+ searchFields = getSearchFields (context , nestedFieldsVisitor , nestedSubDocId ,
275
+ storedToRequestedFields , subReaderContext );
276
+ }
247
277
248
- Map <String , DocumentField > searchFields =
249
- getSearchFields (context , nestedSubDocId , fieldNames , fieldNamePatterns , subReaderContext );
250
278
DocumentMapper documentMapper = context .mapperService ().documentMapper (uid .type ());
251
279
SourceLookup sourceLookup = context .lookup ().source ();
252
280
sourceLookup .setSegmentAndDocument (subReaderContext , nestedSubDocId );
@@ -307,26 +335,6 @@ private SearchHit createNestedSearchHit(SearchContext context, int nestedTopDocI
307
335
return new SearchHit (nestedTopDocId , uid .id (), documentMapper .typeText (), nestedIdentity , searchFields );
308
336
}
309
337
310
- private Map <String , DocumentField > getSearchFields (SearchContext context , int nestedSubDocId , Set <String > fieldNames ,
311
- List <String > fieldNamePatterns , LeafReaderContext subReaderContext ) {
312
- Map <String , DocumentField > searchFields = null ;
313
- if (context .hasStoredFields () && !context .storedFieldsContext ().fieldNames ().isEmpty ()) {
314
- FieldsVisitor nestedFieldsVisitor = new CustomFieldsVisitor (fieldNames == null ? Collections .emptySet () : fieldNames ,
315
- fieldNamePatterns == null ? Collections .emptyList () : fieldNamePatterns , false );
316
- if (nestedFieldsVisitor != null ) {
317
- loadStoredFields (context , subReaderContext , nestedFieldsVisitor , nestedSubDocId );
318
- nestedFieldsVisitor .postProcess (context .mapperService ());
319
- if (!nestedFieldsVisitor .fields ().isEmpty ()) {
320
- searchFields = new HashMap <>(nestedFieldsVisitor .fields ().size ());
321
- for (Map .Entry <String , List <Object >> entry : nestedFieldsVisitor .fields ().entrySet ()) {
322
- searchFields .put (entry .getKey (), new DocumentField (entry .getKey (), entry .getValue ()));
323
- }
324
- }
325
- }
326
- }
327
- return searchFields ;
328
- }
329
-
330
338
private SearchHit .NestedIdentity getInternalNestedIdentity (SearchContext context , int nestedSubDocId ,
331
339
LeafReaderContext subReaderContext ,
332
340
MapperService mapperService ,
0 commit comments