@@ -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,45 @@ public static class Builder extends MetadataFieldMapper.Builder {
119
120
Collections .emptyList ()
120
121
);
121
122
123
+ private final Parameter <Boolean > recoverySourceEnabled = Parameter .boolParam (
124
+ "recovery_source_enabled" ,
125
+ false ,
126
+ m -> toType (m ).recoverySourceEnabled ,
127
+ Defaults .ENABLED
128
+ );
129
+
130
+ private final Parameter <List <String >> recoverySourceIncludes = Parameter .stringArrayParam (
131
+ "recovery_source_includes" ,
132
+ false ,
133
+ m -> Arrays .asList (toType (m ).recoverySourceIncludes ),
134
+ Collections .emptyList ()
135
+ );
136
+
137
+ private final Parameter <List <String >> recoverySourceExcludes = Parameter .stringArrayParam (
138
+ "recovery_source_excludes" ,
139
+ false ,
140
+ m -> Arrays .asList (toType (m ).recoverySourceExcludes ),
141
+ Collections .emptyList ()
142
+ );
143
+
122
144
public Builder () {
123
145
super (Defaults .NAME );
124
146
}
125
147
126
148
@ Override
127
149
protected List <Parameter <?>> getParameters () {
128
- return Arrays .asList (enabled , includes , excludes );
150
+ return Arrays .asList (enabled , includes , excludes , recoverySourceEnabled , recoverySourceIncludes , recoverySourceExcludes );
129
151
}
130
152
131
153
@ Override
132
154
public SourceFieldMapper build (BuilderContext context ) {
133
155
return new SourceFieldMapper (
134
156
enabled .getValue (),
135
157
includes .getValue ().toArray (new String [0 ]),
136
- excludes .getValue ().toArray (new String [0 ])
158
+ excludes .getValue ().toArray (new String [0 ]),
159
+ recoverySourceEnabled .getValue (),
160
+ recoverySourceIncludes .getValue ().toArray (new String [0 ]),
161
+ recoverySourceExcludes .getValue ().toArray (new String [0 ])
137
162
);
138
163
}
139
164
}
@@ -173,24 +198,44 @@ public Query termQuery(Object value, QueryShardContext context) {
173
198
}
174
199
175
200
private final boolean enabled ;
201
+ private final boolean recoverySourceEnabled ;
176
202
/** indicates whether the source will always exist and be complete, for use by features like the update API */
177
203
private final boolean complete ;
178
204
179
205
private final String [] includes ;
180
206
private final String [] excludes ;
207
+ private final String [] recoverySourceIncludes ;
208
+ private final String [] recoverySourceExcludes ;
181
209
182
210
private SourceFieldMapper () {
183
- this (Defaults .ENABLED , Strings .EMPTY_ARRAY , Strings .EMPTY_ARRAY );
211
+ this (Defaults .ENABLED , Strings .EMPTY_ARRAY , Strings .EMPTY_ARRAY , Defaults . ENABLED , Strings . EMPTY_ARRAY , Strings . EMPTY_ARRAY );
184
212
}
185
213
186
- private SourceFieldMapper (boolean enabled , String [] includes , String [] excludes ) {
214
+ private SourceFieldMapper (
215
+ boolean enabled ,
216
+ String [] includes ,
217
+ String [] excludes ,
218
+ boolean recoverySourceEnabled ,
219
+ String [] recoverySourceIncludes ,
220
+ String [] recoverySourceExcludes
221
+ ) {
187
222
super (new SourceFieldType (enabled ));
188
223
this .enabled = enabled ;
189
224
this .includes = includes ;
190
225
this .excludes = excludes ;
191
226
final boolean filtered = CollectionUtils .isEmpty (includes ) == false || CollectionUtils .isEmpty (excludes ) == false ;
192
227
this .filter = enabled && filtered ? XContentMapValues .filter (includes , excludes ) : null ;
193
228
this .complete = enabled && CollectionUtils .isEmpty (includes ) && CollectionUtils .isEmpty (excludes );
229
+
230
+ // Set parameters for recovery source
231
+ this .recoverySourceEnabled = recoverySourceEnabled ;
232
+ this .recoverySourceIncludes = recoverySourceIncludes ;
233
+ this .recoverySourceExcludes = recoverySourceExcludes ;
234
+ final boolean recoverySourcefiltered = CollectionUtils .isEmpty (recoverySourceIncludes ) == false
235
+ || CollectionUtils .isEmpty (recoverySourceExcludes ) == false ;
236
+ this .recoverySourceFilter = this .recoverySourceEnabled && recoverySourcefiltered
237
+ ? XContentMapValues .filter (recoverySourceIncludes , recoverySourceExcludes )
238
+ : null ;
194
239
}
195
240
196
241
public boolean enabled () {
@@ -212,22 +257,40 @@ public void preParse(ParseContext context) throws IOException {
212
257
context .doc ().add (new StoredField (fieldType ().name (), ref .bytes , ref .offset , ref .length ));
213
258
}
214
259
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 ));
260
+ if (recoverySourceEnabled ) {
261
+ if (originalSource != null && adaptedSource != originalSource ) {
262
+ final BytesReference adaptedRecoverySource = applyFilters (
263
+ originalSource ,
264
+ contentType ,
265
+ recoverySourceEnabled ,
266
+ recoverySourceFilter
267
+ );
268
+ // if we omitted source or modified it we add the _recovery_source to ensure we have it for ops based recovery
269
+ BytesRef ref = adaptedRecoverySource .toBytesRef ();
270
+ context .doc ().add (new StoredField (RECOVERY_SOURCE_NAME , ref .bytes , ref .offset , ref .length ));
271
+ context .doc ().add (new NumericDocValuesField (RECOVERY_SOURCE_NAME , 1 ));
272
+ }
220
273
}
221
274
}
222
275
223
276
@ Nullable
224
277
public BytesReference applyFilters (@ Nullable BytesReference originalSource , @ Nullable MediaType contentType ) throws IOException {
225
- if (enabled && originalSource != null ) {
278
+ return applyFilters (originalSource , contentType , enabled , filter );
279
+ }
280
+
281
+ @ Nullable
282
+ private BytesReference applyFilters (
283
+ @ Nullable BytesReference originalSource ,
284
+ @ Nullable MediaType contentType ,
285
+ boolean isProvidedSourceEnabled ,
286
+ @ Nullable final Function <Map <String , ?>, Map <String , Object >> filters
287
+ ) throws IOException {
288
+ if (isProvidedSourceEnabled && originalSource != null ) {
226
289
// 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 ) {
290
+ if (filters != null ) {
228
291
// we don't update the context source if we filter, we want to keep it as is...
229
292
Tuple <? extends MediaType , Map <String , Object >> mapTuple = XContentHelper .convertToMap (originalSource , true , contentType );
230
- Map <String , Object > filteredSource = filter .apply (mapTuple .v2 ());
293
+ Map <String , Object > filteredSource = filters .apply (mapTuple .v2 ());
231
294
BytesStreamOutput bStream = new BytesStreamOutput ();
232
295
MediaType actualContentType = mapTuple .v1 ();
233
296
XContentBuilder builder = MediaTypeRegistry .contentBuilder (actualContentType , bStream ).map (filteredSource );
0 commit comments