@@ -74,6 +74,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
74
74
75
75
public static final String CONTENT_TYPE = "_source" ;
76
76
private final Function <Map <String , ?>, Map <String , Object >> filter ;
77
+ private final Function <Map <String , ?>, Map <String , Object >> recoverySourceFilter ;
77
78
78
79
/**
79
80
* Default parameters for source fields
@@ -119,21 +120,34 @@ public static class Builder extends MetadataFieldMapper.Builder {
119
120
Collections .emptyList ()
120
121
);
121
122
123
+ private final Parameter <Boolean > recoverySourceEnabled = Parameter .boolParam ("recovery_source_enabled" ,
124
+ false , m -> toType (m ).recoverySourceEnabled , Defaults .ENABLED );
125
+
126
+ private final Parameter <List <String >> recoverySourceIncludes = Parameter .stringArrayParam (
127
+ "recovery_source_includes" , false , m ->Arrays .asList (toType (m ).recoverySourceIncludes ), Collections .emptyList ());
128
+
129
+ private final Parameter <List <String >> recoverySourceExcludes = Parameter .stringArrayParam (
130
+ "recovery_source_excludes" , false , m ->Arrays .asList (toType (m ).recoverySourceExcludes ),
131
+ Collections .emptyList ());
132
+
122
133
public Builder () {
123
134
super (Defaults .NAME );
124
135
}
125
136
126
137
@ Override
127
138
protected List <Parameter <?>> getParameters () {
128
- return Arrays .asList (enabled , includes , excludes );
139
+ return Arrays .asList (enabled , includes , excludes , recoverySourceEnabled , recoverySourceIncludes , recoverySourceExcludes );
129
140
}
130
141
131
142
@ Override
132
143
public SourceFieldMapper build (BuilderContext context ) {
133
144
return new SourceFieldMapper (
134
145
enabled .getValue (),
135
146
includes .getValue ().toArray (new String [0 ]),
136
- excludes .getValue ().toArray (new String [0 ])
147
+ excludes .getValue ().toArray (new String [0 ]),
148
+ recoverySourceEnabled .getValue (),
149
+ recoverySourceIncludes .getValue ().toArray (new String [0 ]),
150
+ recoverySourceExcludes .getValue ().toArray (new String [0 ])
137
151
);
138
152
}
139
153
}
@@ -173,24 +187,36 @@ public Query termQuery(Object value, QueryShardContext context) {
173
187
}
174
188
175
189
private final boolean enabled ;
190
+ private final boolean recoverySourceEnabled ;
176
191
/** indicates whether the source will always exist and be complete, for use by features like the update API */
177
192
private final boolean complete ;
178
193
179
194
private final String [] includes ;
180
195
private final String [] excludes ;
196
+ private final String [] recoverySourceIncludes ;
197
+ private final String [] recoverySourceExcludes ;
181
198
182
199
private SourceFieldMapper () {
183
- this (Defaults .ENABLED , Strings .EMPTY_ARRAY , Strings .EMPTY_ARRAY );
200
+ this (Defaults .ENABLED , Strings .EMPTY_ARRAY , Strings .EMPTY_ARRAY , Defaults . ENABLED , Strings . EMPTY_ARRAY , Strings . EMPTY_ARRAY );
184
201
}
185
202
186
- private SourceFieldMapper (boolean enabled , String [] includes , String [] excludes ) {
203
+ private SourceFieldMapper (boolean enabled , String [] includes , String [] excludes , boolean recoverySourceEnabled ,
204
+ String [] recoverySourceIncludes , String [] recoverySourceExcludes ) {
187
205
super (new SourceFieldType (enabled ));
188
206
this .enabled = enabled ;
189
207
this .includes = includes ;
190
208
this .excludes = excludes ;
191
209
final boolean filtered = CollectionUtils .isEmpty (includes ) == false || CollectionUtils .isEmpty (excludes ) == false ;
192
210
this .filter = enabled && filtered ? XContentMapValues .filter (includes , excludes ) : null ;
193
211
this .complete = enabled && CollectionUtils .isEmpty (includes ) && CollectionUtils .isEmpty (excludes );
212
+
213
+ // Set parameters for recovery source
214
+ this .recoverySourceEnabled = recoverySourceEnabled ;
215
+ this .recoverySourceIncludes = recoverySourceIncludes ;
216
+ this .recoverySourceExcludes = recoverySourceExcludes ;
217
+ final boolean recoverySourcefiltered =
218
+ CollectionUtils .isEmpty (recoverySourceIncludes ) == false || CollectionUtils .isEmpty (recoverySourceExcludes ) == false ;
219
+ this .recoverySourceFilter = this .recoverySourceEnabled && recoverySourcefiltered ? XContentMapValues .filter (recoverySourceIncludes , recoverySourceExcludes ) : null ;
194
220
}
195
221
196
222
public boolean enabled () {
@@ -212,22 +238,32 @@ public void preParse(ParseContext context) throws IOException {
212
238
context .doc ().add (new StoredField (fieldType ().name (), ref .bytes , ref .offset , ref .length ));
213
239
}
214
240
215
- if (originalSource != null && adaptedSource != originalSource ) {
216
- // if we omitted source or modified it we add the _recovery_source to ensure we have it for ops based recovery
217
- BytesRef ref = originalSource .toBytesRef ();
218
- context .doc ().add (new StoredField (RECOVERY_SOURCE_NAME , ref .bytes , ref .offset , ref .length ));
219
- context .doc ().add (new NumericDocValuesField (RECOVERY_SOURCE_NAME , 1 ));
241
+ if (recoverySourceEnabled ) {
242
+ if (originalSource != null && adaptedSource != originalSource ) {
243
+ final BytesReference adaptedRecoverySource = applyFilters (originalSource , contentType ,
244
+ recoverySourceEnabled , recoverySourceFilter );
245
+ // if we omitted source or modified it we add the _recovery_source to ensure we have it for ops based recovery
246
+ BytesRef ref = adaptedRecoverySource .toBytesRef ();
247
+ context .doc ().add (new StoredField (RECOVERY_SOURCE_NAME , ref .bytes , ref .offset , ref .length ));
248
+ context .doc ().add (new NumericDocValuesField (RECOVERY_SOURCE_NAME , 1 ));
249
+ }
220
250
}
221
251
}
222
252
223
253
@ Nullable
224
254
public BytesReference applyFilters (@ Nullable BytesReference originalSource , @ Nullable MediaType contentType ) throws IOException {
225
- if (enabled && originalSource != null ) {
255
+ return applyFilters (originalSource , contentType , enabled , filter );
256
+ }
257
+
258
+ @ Nullable
259
+ private BytesReference applyFilters (@ Nullable BytesReference originalSource , @ Nullable MediaType contentType ,
260
+ boolean isProvidedSourceEnabled , @ Nullable final Function <Map <String , ?>, Map <String , Object >> filters ) throws IOException {
261
+ if (isProvidedSourceEnabled && originalSource != null ) {
226
262
// Percolate and tv APIs may not set the source and that is ok, because these APIs will not index any data
227
- if (filter != null ) {
263
+ if (filters != null ) {
228
264
// we don't update the context source if we filter, we want to keep it as is...
229
265
Tuple <? extends MediaType , Map <String , Object >> mapTuple = XContentHelper .convertToMap (originalSource , true , contentType );
230
- Map <String , Object > filteredSource = filter .apply (mapTuple .v2 ());
266
+ Map <String , Object > filteredSource = filters .apply (mapTuple .v2 ());
231
267
BytesStreamOutput bStream = new BytesStreamOutput ();
232
268
MediaType actualContentType = mapTuple .v1 ();
233
269
XContentBuilder builder = MediaTypeRegistry .contentBuilder (actualContentType , bStream ).map (filteredSource );
0 commit comments