28
28
import org .apache .lucene .tests .index .RandomIndexWriter ;
29
29
import org .apache .lucene .util .BytesRef ;
30
30
import org .elasticsearch .common .lucene .search .function .ScriptScoreQuery ;
31
+ import org .elasticsearch .common .settings .Settings ;
31
32
import org .elasticsearch .index .IndexVersion ;
32
33
import org .elasticsearch .index .fielddata .DoubleScriptFieldData ;
33
34
import org .elasticsearch .index .fielddata .ScriptDocValues ;
40
41
import org .elasticsearch .script .ScriptFactory ;
41
42
import org .elasticsearch .script .ScriptType ;
42
43
import org .elasticsearch .search .MultiValueMode ;
44
+ import org .elasticsearch .search .lookup .SearchLookup ;
43
45
44
46
import java .io .IOException ;
45
47
import java .util .ArrayList ;
46
48
import java .util .List ;
47
49
import java .util .Map ;
48
50
49
51
import static java .util .Collections .emptyMap ;
52
+ import static org .elasticsearch .index .mapper .LongScriptFieldTypeTests .createDocumentWithIgnoredSource ;
50
53
import static org .hamcrest .Matchers .containsInAnyOrder ;
51
54
import static org .hamcrest .Matchers .equalTo ;
55
+ import static org .hamcrest .Matchers .instanceOf ;
56
+ import static org .hamcrest .Matchers .nullValue ;
52
57
53
58
public class DoubleScriptFieldTypeTests extends AbstractNonTextScriptFieldTypeTestCase {
54
59
@@ -269,6 +274,69 @@ public void testBlockLoader() throws IOException {
269
274
}
270
275
}
271
276
277
+ public void testBlockLoaderSourceOnlyRuntimeField () throws IOException {
278
+ try (
279
+ Directory directory = newDirectory ();
280
+ RandomIndexWriter iw = new RandomIndexWriter (random (), directory , newIndexWriterConfig ().setMergePolicy (NoMergePolicy .INSTANCE ))
281
+ ) {
282
+ iw .addDocuments (
283
+ List .of (
284
+ List .of (new StoredField ("_source" , new BytesRef ("{\" test\" : [1.1]}" ))),
285
+ List .of (new StoredField ("_source" , new BytesRef ("{\" test\" : [2.1]}" )))
286
+ )
287
+ );
288
+ try (DirectoryReader reader = iw .getReader ()) {
289
+ DoubleScriptFieldType fieldType = simpleSourceOnlyMappedFieldType ();
290
+
291
+ // Assert implementations:
292
+ BlockLoader loader = fieldType .blockLoader (blContext (Settings .EMPTY , true ));
293
+ assertThat (loader , instanceOf (DoubleScriptBlockDocValuesReader .DoubleScriptBlockLoader .class ));
294
+ // ignored source doesn't support column at a time loading:
295
+ var columnAtATimeLoader = loader .columnAtATimeReader (reader .leaves ().getFirst ());
296
+ assertThat (columnAtATimeLoader , instanceOf (DoubleScriptBlockDocValuesReader .class ));
297
+ var rowStrideReader = loader .rowStrideReader (reader .leaves ().getFirst ());
298
+ assertThat (rowStrideReader , instanceOf (DoubleScriptBlockDocValuesReader .class ));
299
+
300
+ // Assert values:
301
+ assertThat (blockLoaderReadValuesFromColumnAtATimeReader (reader , fieldType , 0 ), equalTo (List .of (1.1 , 2.1 )));
302
+ assertThat (blockLoaderReadValuesFromColumnAtATimeReader (reader , fieldType , 1 ), equalTo (List .of (2.1 )));
303
+ assertThat (blockLoaderReadValuesFromRowStrideReader (reader , fieldType ), equalTo (List .of (1.1 , 2.1 )));
304
+ }
305
+ }
306
+ }
307
+
308
+ public void testBlockLoaderSourceOnlyRuntimeFieldWithSyntheticSource () throws IOException {
309
+ var settings = Settings .builder ().put ("index.mapping.source.mode" , "synthetic" ).build ();
310
+ try (
311
+ Directory directory = newDirectory ();
312
+ RandomIndexWriter iw = new RandomIndexWriter (random (), directory , newIndexWriterConfig ().setMergePolicy (NoMergePolicy .INSTANCE ))
313
+ ) {
314
+
315
+ var document1 = createDocumentWithIgnoredSource ("[1.1]" );
316
+ var document2 = createDocumentWithIgnoredSource ("[2.1]" );
317
+
318
+ iw .addDocuments (List .of (document1 , document2 ));
319
+ try (DirectoryReader reader = iw .getReader ()) {
320
+ DoubleScriptFieldType fieldType = simpleSourceOnlyMappedFieldType ();
321
+
322
+ // Assert implementations:
323
+ BlockLoader loader = fieldType .blockLoader (blContext (settings , true ));
324
+ assertThat (loader , instanceOf (FallbackSyntheticSourceBlockLoader .class ));
325
+ // ignored source doesn't support column at a time loading:
326
+ var columnAtATimeLoader = loader .columnAtATimeReader (reader .leaves ().getFirst ());
327
+ assertThat (columnAtATimeLoader , nullValue ());
328
+ var rowStrideReader = loader .rowStrideReader (reader .leaves ().getFirst ());
329
+ assertThat (
330
+ rowStrideReader .getClass ().getName (),
331
+ equalTo ("org.elasticsearch.index.mapper.FallbackSyntheticSourceBlockLoader$IgnoredSourceRowStrideReader" )
332
+ );
333
+
334
+ // Assert values:
335
+ assertThat (blockLoaderReadValuesFromRowStrideReader (settings , reader , fieldType , true ), equalTo (List .of (1.1 , 2.1 )));
336
+ }
337
+ }
338
+ }
339
+
272
340
@ Override
273
341
protected Query randomTermsQuery (MappedFieldType ft , SearchExecutionContext ctx ) {
274
342
return ft .termsQuery (List .of (randomLong ()), ctx );
@@ -279,6 +347,10 @@ protected DoubleScriptFieldType simpleMappedFieldType() {
279
347
return build ("read_foo" , Map .of (), OnScriptError .FAIL );
280
348
}
281
349
350
+ private DoubleScriptFieldType simpleSourceOnlyMappedFieldType () {
351
+ return build ("read_test" , Map .of (), OnScriptError .FAIL );
352
+ }
353
+
282
354
@ Override
283
355
protected MappedFieldType loopFieldType () {
284
356
return build ("loop" , Map .of (), OnScriptError .FAIL );
@@ -296,6 +368,31 @@ protected DoubleScriptFieldType build(String code, Map<String, Object> params, O
296
368
297
369
private static DoubleFieldScript .Factory factory (Script script ) {
298
370
return switch (script .getIdOrCode ()) {
371
+ case "read_test" -> new DoubleFieldScript .Factory () {
372
+ @ Override
373
+ public DoubleFieldScript .LeafFactory newFactory (
374
+ String fieldName ,
375
+ Map <String , Object > params ,
376
+ SearchLookup lookup ,
377
+ OnScriptError onScriptError
378
+ ) {
379
+ return (ctx ) -> new DoubleFieldScript (fieldName , params , lookup , onScriptError , ctx ) {
380
+ @ Override
381
+ @ SuppressWarnings ("unchecked" )
382
+ public void execute () {
383
+ Map <String , Object > source = (Map <String , Object >) this .getParams ().get ("_source" );
384
+ for (Object foo : (List <?>) source .get ("test" )) {
385
+ emit (((Number ) foo ).doubleValue ());
386
+ }
387
+ };
388
+ };
389
+ }
390
+
391
+ @ Override
392
+ public boolean isParsedFromSource () {
393
+ return true ;
394
+ }
395
+ };
299
396
case "read_foo" -> (fieldName , params , lookup , onScriptError ) -> (ctx ) -> new DoubleFieldScript (
300
397
fieldName ,
301
398
params ,
0 commit comments