21
21
22
22
import org .elasticsearch .common .document .DocumentField ;
23
23
import org .elasticsearch .common .xcontent .support .XContentMapValues ;
24
- import org .elasticsearch .index .mapper .DocumentMapper ;
24
+ import org .elasticsearch .index .mapper .MappedFieldType ;
25
25
import org .elasticsearch .index .mapper .MapperService ;
26
26
import org .elasticsearch .search .lookup .SourceLookup ;
27
27
28
+ import java .util .ArrayList ;
28
29
import java .util .Collection ;
29
30
import java .util .HashMap ;
30
31
import java .util .HashSet ;
31
32
import java .util .List ;
32
33
import java .util .Map ;
33
34
import java .util .Set ;
34
35
36
+ /**
37
+ * A helper class to {@link FetchFieldsPhase} that's initialized with a list of field patterns to fetch.
38
+ * Then given a specific document, it can retrieve the corresponding fields from the document's source.
39
+ */
35
40
public class FieldValueRetriever {
36
- private final Set <String > fields ;
41
+ private final List <FieldContext > fieldContexts ;
42
+ private final Set <String > sourcePaths ;
37
43
38
44
public static FieldValueRetriever create (MapperService mapperService ,
39
45
Collection <String > fieldPatterns ) {
40
- Set < String > fields = new HashSet <>();
41
- DocumentMapper documentMapper = mapperService . documentMapper ();
46
+ List < FieldContext > fields = new ArrayList <>();
47
+ Set < String > sourcePaths = new HashSet <> ();
42
48
43
49
for (String fieldPattern : fieldPatterns ) {
44
- if (documentMapper .objectMappers ().containsKey (fieldPattern )) {
45
- continue ;
46
- }
47
50
Collection <String > concreteFields = mapperService .simpleMatchToFullName (fieldPattern );
48
- fields .addAll (concreteFields );
51
+ for (String field : concreteFields ) {
52
+ MappedFieldType fieldType = mapperService .fieldType (field );
53
+
54
+ if (fieldType != null ) {
55
+ Set <String > sourcePath = mapperService .sourcePath (field );
56
+ fields .add (new FieldContext (field , sourcePath ));
57
+ sourcePaths .addAll (sourcePath );
58
+ }
59
+ }
49
60
}
50
- return new FieldValueRetriever (fields );
61
+
62
+ return new FieldValueRetriever (fields , sourcePaths );
51
63
}
52
64
53
- private FieldValueRetriever (Set <String > fields ) {
54
- this .fields = fields ;
65
+ private FieldValueRetriever (List <FieldContext > fieldContexts , Set <String > sourcePaths ) {
66
+ this .fieldContexts = fieldContexts ;
67
+ this .sourcePaths = sourcePaths ;
55
68
}
56
69
57
70
@ SuppressWarnings ("unchecked" )
58
71
public Map <String , DocumentField > retrieve (SourceLookup sourceLookup ) {
59
72
Map <String , DocumentField > result = new HashMap <>();
60
- Map <String , Object > sourceValues = extractValues (sourceLookup , this .fields );
73
+ Map <String , Object > sourceValues = extractValues (sourceLookup , sourcePaths );
74
+
75
+ for (FieldContext fieldContext : fieldContexts ) {
76
+ String field = fieldContext .fieldName ;
77
+ Set <String > sourcePath = fieldContext .sourcePath ;
61
78
62
- for (Map .Entry <String , Object > entry : sourceValues .entrySet ()) {
63
- String field = entry .getKey ();
64
- Object value = entry .getValue ();
65
- List <Object > values = value instanceof List
66
- ? (List <Object >) value
67
- : List .of (value );
79
+ List <Object > values = new ArrayList <>();
80
+ for (String path : sourcePath ) {
81
+ Object value = sourceValues .get (path );
82
+ if (value != null ) {
83
+ if (value instanceof List ) {
84
+ values .addAll ((List <Object >) value );
85
+ } else {
86
+ values .add (value );
87
+ }
88
+ }
89
+ }
68
90
result .put (field , new DocumentField (field , values ));
69
91
}
70
92
return result ;
@@ -74,7 +96,7 @@ public Map<String, DocumentField> retrieve(SourceLookup sourceLookup) {
74
96
* For each of the provided paths, return its value in the source. Note that in contrast with
75
97
* {@link SourceLookup#extractRawValues}, array and object values can be returned.
76
98
*/
77
- private static Map <String , Object > extractValues (SourceLookup sourceLookup , Collection <String > paths ) {
99
+ private static Map <String , Object > extractValues (SourceLookup sourceLookup , Set <String > paths ) {
78
100
Map <String , Object > result = new HashMap <>(paths .size ());
79
101
for (String path : paths ) {
80
102
Object value = XContentMapValues .extractValue (path , sourceLookup );
@@ -84,4 +106,14 @@ private static Map<String, Object> extractValues(SourceLookup sourceLookup, Coll
84
106
}
85
107
return result ;
86
108
}
109
+
110
+ private static class FieldContext {
111
+ final String fieldName ;
112
+ final Set <String > sourcePath ;
113
+
114
+ FieldContext (String fieldName , Set <String > sourcePath ) {
115
+ this .fieldName = fieldName ;
116
+ this .sourcePath = sourcePath ;
117
+ }
118
+ }
87
119
}
0 commit comments