3030import org .elasticsearch .common .collect .Tuple ;
3131import org .elasticsearch .common .inject .Inject ;
3232import org .elasticsearch .common .lucene .search .Queries ;
33+ import org .elasticsearch .common .regex .Regex ;
3334import org .elasticsearch .common .text .StringAndBytesText ;
3435import org .elasticsearch .common .text .Text ;
3536import org .elasticsearch .common .xcontent .XContentHelper ;
3637import org .elasticsearch .common .xcontent .XContentType ;
3738import org .elasticsearch .common .xcontent .support .XContentMapValues ;
38- import org .elasticsearch .index .fieldvisitor .AllFieldsVisitor ;
3939import org .elasticsearch .index .fieldvisitor .CustomFieldsVisitor ;
4040import org .elasticsearch .index .fieldvisitor .FieldsVisitor ;
4141import org .elasticsearch .index .mapper .DocumentMapper ;
5555import org .elasticsearch .search .lookup .SourceLookup ;
5656
5757import java .io .IOException ;
58- import java .util .ArrayList ;
59- import java .util .Collections ;
60- import java .util .HashMap ;
61- import java .util .HashSet ;
62- import java .util .List ;
63- import java .util .Map ;
64- import java .util .Set ;
58+ import java .util .*;
6559
6660import static java .util .Collections .unmodifiableMap ;
6761import static org .elasticsearch .common .xcontent .XContentFactory .contentBuilder ;
@@ -98,9 +92,7 @@ public void preProcess(SearchContext context) {
9892 public void execute (SearchContext context ) {
9993 FieldsVisitor fieldsVisitor ;
10094 Set <String > fieldNames = null ;
101- List <String > extractFieldNames = null ;
102-
103- boolean loadAllStored = false ;
95+ List <String > fieldNamePatterns = null ;
10496 if (!context .hasFieldNames ()) {
10597 // no fields specified, default to return source if no explicit indication
10698 if (!context .hasScriptFields () && !context .hasFetchSourceContext ()) {
@@ -111,10 +103,6 @@ public void execute(SearchContext context) {
111103 fieldsVisitor = new FieldsVisitor (context .sourceRequested ());
112104 } else {
113105 for (String fieldName : context .fieldNames ()) {
114- if (fieldName .equals ("*" )) {
115- loadAllStored = true ;
116- continue ;
117- }
118106 if (fieldName .equals (SourceFieldMapper .NAME )) {
119107 if (context .hasFetchSourceContext ()) {
120108 context .fetchSourceContext ().fetchSource (true );
@@ -123,32 +111,28 @@ public void execute(SearchContext context) {
123111 }
124112 continue ;
125113 }
126- MappedFieldType fieldType = context .smartNameFieldType (fieldName );
127- if (fieldType == null ) {
128- // Only fail if we know it is a object field, missing paths / fields shouldn't fail.
129- if (context .getObjectMapper (fieldName ) != null ) {
130- throw new IllegalArgumentException ("field [" + fieldName + "] isn't a leaf field" );
114+ if (Regex .isSimpleMatchPattern (fieldName )) {
115+ if (fieldNamePatterns == null ) {
116+ fieldNamePatterns = new ArrayList <>();
117+ }
118+ fieldNamePatterns .add (fieldName );
119+ } else {
120+ MappedFieldType fieldType = context .smartNameFieldType (fieldName );
121+ if (fieldType == null ) {
122+ // Only fail if we know it is a object field, missing paths / fields shouldn't fail.
123+ if (context .getObjectMapper (fieldName ) != null ) {
124+ throw new IllegalArgumentException ("field [" + fieldName + "] isn't a leaf field" );
125+ }
131126 }
132- } else if (fieldType .stored ()) {
133127 if (fieldNames == null ) {
134128 fieldNames = new HashSet <>();
135129 }
136- fieldNames .add (fieldType .names ().indexName ());
137- } else {
138- if (extractFieldNames == null ) {
139- extractFieldNames = new ArrayList <>();
140- }
141- extractFieldNames .add (fieldName );
130+ fieldNames .add (fieldName );
142131 }
143132 }
144- if (loadAllStored ) {
145- fieldsVisitor = new AllFieldsVisitor (); // load everything, including _source
146- } else if (fieldNames != null ) {
147- boolean loadSource = extractFieldNames != null || context .sourceRequested ();
148- fieldsVisitor = new CustomFieldsVisitor (fieldNames , loadSource );
149- } else {
150- fieldsVisitor = new FieldsVisitor (extractFieldNames != null || context .sourceRequested ());
151- }
133+ boolean loadSource = context .sourceRequested ();
134+ fieldsVisitor = new CustomFieldsVisitor (fieldNames == null ? Collections .emptySet () : fieldNames ,
135+ fieldNamePatterns == null ? Collections .emptyList () : fieldNamePatterns , loadSource );
152136 }
153137
154138 InternalSearchHit [] hits = new InternalSearchHit [context .docIdsToLoadSize ()];
@@ -163,9 +147,9 @@ public void execute(SearchContext context) {
163147 try {
164148 int rootDocId = findRootDocumentIfNested (context , subReaderContext , subDocId );
165149 if (rootDocId != -1 ) {
166- searchHit = createNestedSearchHit (context , docId , subDocId , rootDocId , extractFieldNames , loadAllStored , fieldNames , subReaderContext );
150+ searchHit = createNestedSearchHit (context , docId , subDocId , rootDocId , fieldNames , fieldNamePatterns , subReaderContext );
167151 } else {
168- searchHit = createSearchHit (context , fieldsVisitor , docId , subDocId , extractFieldNames , subReaderContext );
152+ searchHit = createSearchHit (context , fieldsVisitor , docId , subDocId , subReaderContext );
169153 }
170154 } catch (IOException e ) {
171155 throw ExceptionsHelper .convertToElastic (e );
@@ -199,7 +183,7 @@ private int findRootDocumentIfNested(SearchContext context, LeafReaderContext su
199183 return -1 ;
200184 }
201185
202- private InternalSearchHit createSearchHit (SearchContext context , FieldsVisitor fieldsVisitor , int docId , int subDocId , List < String > extractFieldNames , LeafReaderContext subReaderContext ) {
186+ private InternalSearchHit createSearchHit (SearchContext context , FieldsVisitor fieldsVisitor , int docId , int subDocId , LeafReaderContext subReaderContext ) {
203187 loadStoredFields (context , subReaderContext , fieldsVisitor , subDocId );
204188 fieldsVisitor .postProcess (context .mapperService ());
205189
@@ -219,45 +203,24 @@ private InternalSearchHit createSearchHit(SearchContext context, FieldsVisitor f
219203 typeText = documentMapper .typeText ();
220204 }
221205 InternalSearchHit searchHit = new InternalSearchHit (docId , fieldsVisitor .uid ().id (), typeText , searchFields );
222-
223- // go over and extract fields that are not mapped / stored
206+ // Set _source if requested.
224207 SourceLookup sourceLookup = context .lookup ().source ();
225208 sourceLookup .setSegmentAndDocument (subReaderContext , subDocId );
226209 if (fieldsVisitor .source () != null ) {
227210 sourceLookup .setSource (fieldsVisitor .source ());
228211 }
229- if (extractFieldNames != null ) {
230- for (String extractFieldName : extractFieldNames ) {
231- List <Object > values = context .lookup ().source ().extractRawValues (extractFieldName );
232- if (!values .isEmpty ()) {
233- if (searchHit .fieldsOrNull () == null ) {
234- searchHit .fields (new HashMap <String , SearchHitField >(2 ));
235- }
236-
237- SearchHitField hitField = searchHit .fields ().get (extractFieldName );
238- if (hitField == null ) {
239- hitField = new InternalSearchHitField (extractFieldName , new ArrayList <>(2 ));
240- searchHit .fields ().put (extractFieldName , hitField );
241- }
242- for (Object value : values ) {
243- hitField .values ().add (value );
244- }
245- }
246- }
247- }
248-
249212 return searchHit ;
250213 }
251214
252- private InternalSearchHit createNestedSearchHit (SearchContext context , int nestedTopDocId , int nestedSubDocId , int rootSubDocId , List <String > extractFieldNames , boolean loadAllStored , Set <String > fieldNames , LeafReaderContext subReaderContext ) throws IOException {
215+ private InternalSearchHit createNestedSearchHit (SearchContext context , int nestedTopDocId , int nestedSubDocId , int rootSubDocId , Set <String > fieldNames , List <String > fieldNamePatterns , LeafReaderContext subReaderContext ) throws IOException {
253216 // Also if highlighting is requested on nested documents we need to fetch the _source from the root document,
254217 // otherwise highlighting will attempt to fetch the _source from the nested doc, which will fail,
255218 // because the entire _source is only stored with the root document.
256- final FieldsVisitor rootFieldsVisitor = new FieldsVisitor (context .sourceRequested () || extractFieldNames != null || context .highlight () != null );
219+ final FieldsVisitor rootFieldsVisitor = new FieldsVisitor (context .sourceRequested () || context .highlight () != null );
257220 loadStoredFields (context , subReaderContext , rootFieldsVisitor , rootSubDocId );
258221 rootFieldsVisitor .postProcess (context .mapperService ());
259222
260- Map <String , SearchHitField > searchFields = getSearchFields (context , nestedSubDocId , loadAllStored , fieldNames , subReaderContext );
223+ Map <String , SearchHitField > searchFields = getSearchFields (context , nestedSubDocId , fieldNames , fieldNamePatterns , subReaderContext );
261224 DocumentMapper documentMapper = context .mapperService ().documentMapper (rootFieldsVisitor .uid ().type ());
262225 SourceLookup sourceLookup = context .lookup ().source ();
263226 sourceLookup .setSegmentAndDocument (subReaderContext , nestedSubDocId );
@@ -299,39 +262,14 @@ private InternalSearchHit createNestedSearchHit(SearchContext context, int neste
299262 }
300263
301264 InternalSearchHit searchHit = new InternalSearchHit (nestedTopDocId , rootFieldsVisitor .uid ().id (), documentMapper .typeText (), nestedIdentity , searchFields );
302- if (extractFieldNames != null ) {
303- for (String extractFieldName : extractFieldNames ) {
304- List <Object > values = context .lookup ().source ().extractRawValues (extractFieldName );
305- if (!values .isEmpty ()) {
306- if (searchHit .fieldsOrNull () == null ) {
307- searchHit .fields (new HashMap <String , SearchHitField >(2 ));
308- }
309-
310- SearchHitField hitField = searchHit .fields ().get (extractFieldName );
311- if (hitField == null ) {
312- hitField = new InternalSearchHitField (extractFieldName , new ArrayList <>(2 ));
313- searchHit .fields ().put (extractFieldName , hitField );
314- }
315- for (Object value : values ) {
316- hitField .values ().add (value );
317- }
318- }
319- }
320- }
321-
322265 return searchHit ;
323266 }
324267
325- private Map <String , SearchHitField > getSearchFields (SearchContext context , int nestedSubDocId , boolean loadAllStored , Set <String > fieldNames , LeafReaderContext subReaderContext ) {
268+ private Map <String , SearchHitField > getSearchFields (SearchContext context , int nestedSubDocId , Set < String > fieldNames , List <String > fieldNamePatterns , LeafReaderContext subReaderContext ) {
326269 Map <String , SearchHitField > searchFields = null ;
327270 if (context .hasFieldNames () && !context .fieldNames ().isEmpty ()) {
328- FieldsVisitor nestedFieldsVisitor = null ;
329- if (loadAllStored ) {
330- nestedFieldsVisitor = new AllFieldsVisitor ();
331- } else if (fieldNames != null ) {
332- nestedFieldsVisitor = new CustomFieldsVisitor (fieldNames , false );
333- }
334-
271+ FieldsVisitor nestedFieldsVisitor = new CustomFieldsVisitor (fieldNames == null ? Collections .emptySet () : fieldNames ,
272+ fieldNamePatterns == null ? Collections .emptyList () : fieldNamePatterns , false );
335273 if (nestedFieldsVisitor != null ) {
336274 loadStoredFields (context , subReaderContext , nestedFieldsVisitor , nestedSubDocId );
337275 nestedFieldsVisitor .postProcess (context .mapperService ());
0 commit comments