13
13
import org .apache .lucene .document .SortedNumericDocValuesField ;
14
14
import org .apache .lucene .document .StoredField ;
15
15
import org .apache .lucene .index .IndexOptions ;
16
+ import org .apache .lucene .index .LeafReaderContext ;
16
17
import org .apache .lucene .search .Query ;
17
18
import org .apache .lucene .search .TermRangeQuery ;
18
19
import org .apache .lucene .util .BytesRef ;
25
26
import org .elasticsearch .index .fielddata .IndexNumericFieldData .NumericType ;
26
27
import org .elasticsearch .index .fielddata .plain .SortedNumericIndexFieldData ;
27
28
import org .elasticsearch .index .query .SearchExecutionContext ;
29
+ import org .elasticsearch .script .BooleanFieldScript ;
30
+ import org .elasticsearch .script .Script ;
31
+ import org .elasticsearch .script .ScriptCompiler ;
28
32
import org .elasticsearch .search .DocValueFormat ;
33
+ import org .elasticsearch .search .lookup .FieldValues ;
29
34
import org .elasticsearch .search .lookup .SearchLookup ;
30
35
31
36
import java .io .IOException ;
34
39
import java .util .Collections ;
35
40
import java .util .List ;
36
41
import java .util .Map ;
42
+ import java .util .Objects ;
37
43
import java .util .function .Supplier ;
38
44
39
45
/**
@@ -74,44 +80,69 @@ public static class Builder extends FieldMapper.Builder {
74
80
.acceptsNull ();
75
81
76
82
private final Parameter <Float > boost = Parameter .boostParam ();
83
+ private final Parameter <Script > script = Parameter .scriptParam (m -> toType (m ).script );
84
+ private final Parameter <String > onScriptError = Parameter .onScriptErrorParam (m -> toType (m ).onScriptError , script );
85
+
77
86
private final Parameter <Map <String , String >> meta = Parameter .metaParam ();
78
87
79
- public Builder (String name ) {
88
+ private final ScriptCompiler scriptCompiler ;
89
+
90
+ public Builder (String name , ScriptCompiler scriptCompiler ) {
80
91
super (name );
92
+ this .scriptCompiler = Objects .requireNonNull (scriptCompiler );
93
+ this .script .precludesParameters (nullValue );
94
+ this .script .setValidator (s -> {
95
+ if (s != null && indexed .get () == false && docValues .get () == false ) {
96
+ throw new MapperParsingException ("Cannot define script on field with index:false and doc_values:false" );
97
+ }
98
+ });
81
99
}
82
100
83
101
@ Override
84
102
protected List <Parameter <?>> getParameters () {
85
- return Arrays .asList (meta , boost , docValues , indexed , nullValue , stored );
103
+ return Arrays .asList (meta , boost , docValues , indexed , nullValue , stored , script , onScriptError );
86
104
}
87
105
88
106
@ Override
89
107
public BooleanFieldMapper build (ContentPath contentPath ) {
90
108
MappedFieldType ft = new BooleanFieldType (buildFullName (contentPath ), indexed .getValue (), stored .getValue (),
91
- docValues .getValue (), nullValue .getValue (), meta .getValue ());
109
+ docValues .getValue (), nullValue .getValue (), scriptValues (), meta .getValue ());
92
110
ft .setBoost (boost .getValue ());
93
111
return new BooleanFieldMapper (name , ft , multiFieldsBuilder .build (this , contentPath ), copyTo .build (), this );
94
112
}
113
+
114
+ private FieldValues <Boolean > scriptValues () {
115
+ if (script .get () == null ) {
116
+ return null ;
117
+ }
118
+ BooleanFieldScript .Factory scriptFactory = scriptCompiler .compile (script .get (), BooleanFieldScript .CONTEXT );
119
+ return scriptFactory == null ? null : (lookup , ctx , doc , consumer ) -> scriptFactory
120
+ .newFactory (name , script .get ().getParams (), lookup )
121
+ .newInstance (ctx )
122
+ .runForDoc (doc , consumer );
123
+ }
95
124
}
96
125
97
- public static final TypeParser PARSER = new TypeParser ((n , c ) -> new Builder (n ));
126
+ public static final TypeParser PARSER = new TypeParser ((n , c ) -> new Builder (n , c . scriptCompiler () ));
98
127
99
128
public static final class BooleanFieldType extends TermBasedFieldType {
100
129
101
130
private final Boolean nullValue ;
131
+ private final FieldValues <Boolean > scriptValues ;
102
132
103
133
public BooleanFieldType (String name , boolean isSearchable , boolean isStored , boolean hasDocValues ,
104
- Boolean nullValue , Map <String , String > meta ) {
134
+ Boolean nullValue , FieldValues < Boolean > scriptValues , Map <String , String > meta ) {
105
135
super (name , isSearchable , isStored , hasDocValues , TextSearchInfo .SIMPLE_MATCH_ONLY , meta );
106
136
this .nullValue = nullValue ;
137
+ this .scriptValues = scriptValues ;
107
138
}
108
139
109
140
public BooleanFieldType (String name ) {
110
- this (name , true , false , true , false , Collections .emptyMap ());
141
+ this (name , true , false , true , false , null , Collections .emptyMap ());
111
142
}
112
143
113
144
public BooleanFieldType (String name , boolean searchable ) {
114
- this (name , searchable , false , true , false , Collections .emptyMap ());
145
+ this (name , searchable , false , true , false , null , Collections .emptyMap ());
115
146
}
116
147
117
148
@ Override
@@ -124,7 +155,9 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format)
124
155
if (format != null ) {
125
156
throw new IllegalArgumentException ("Field [" + name () + "] of type [" + typeName () + "] doesn't support formats." );
126
157
}
127
-
158
+ if (this .scriptValues != null ) {
159
+ return FieldValues .valueFetcher (this .scriptValues , context );
160
+ }
128
161
return new SourceValueFetcher (name (), context , nullValue ) {
129
162
@ Override
130
163
protected Boolean parseSourceValue (Object value ) {
@@ -211,14 +244,21 @@ public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower
211
244
private final boolean indexed ;
212
245
private final boolean hasDocValues ;
213
246
private final boolean stored ;
247
+ private final Script script ;
248
+ private final FieldValues <Boolean > scriptValues ;
249
+ private final ScriptCompiler scriptCompiler ;
214
250
215
251
protected BooleanFieldMapper (String simpleName , MappedFieldType mappedFieldType ,
216
252
MultiFields multiFields , CopyTo copyTo , Builder builder ) {
217
- super (simpleName , mappedFieldType , Lucene .KEYWORD_ANALYZER , multiFields , copyTo );
253
+ super (simpleName , mappedFieldType , Lucene .KEYWORD_ANALYZER , multiFields , copyTo ,
254
+ builder .script .get () != null , builder .onScriptError .getValue ());
218
255
this .nullValue = builder .nullValue .getValue ();
219
256
this .stored = builder .stored .getValue ();
220
257
this .indexed = builder .indexed .getValue ();
221
258
this .hasDocValues = builder .docValues .getValue ();
259
+ this .script = builder .script .get ();
260
+ this .scriptValues = builder .scriptValues ();
261
+ this .scriptCompiler = builder .scriptCompiler ;
222
262
}
223
263
224
264
@ Override
@@ -243,7 +283,10 @@ protected void parseCreateField(ParseContext context) throws IOException {
243
283
value = context .parser ().booleanValue ();
244
284
}
245
285
}
286
+ indexValue (context , value );
287
+ }
246
288
289
+ private void indexValue (ParseContext context , Boolean value ) {
247
290
if (value == null ) {
248
291
return ;
249
292
}
@@ -260,14 +303,18 @@ protected void parseCreateField(ParseContext context) throws IOException {
260
303
}
261
304
}
262
305
306
+ @ Override
307
+ protected void indexScriptValues (SearchLookup searchLookup , LeafReaderContext readerContext , int doc , ParseContext parseContext ) {
308
+ this .scriptValues .valuesForDoc (searchLookup , readerContext , doc , value -> indexValue (parseContext , value ));
309
+ }
310
+
263
311
@ Override
264
312
public FieldMapper .Builder getMergeBuilder () {
265
- return new Builder (simpleName ()).init (this );
313
+ return new Builder (simpleName (), scriptCompiler ).init (this );
266
314
}
267
315
268
316
@ Override
269
317
protected String contentType () {
270
318
return CONTENT_TYPE ;
271
319
}
272
-
273
320
}
0 commit comments