37
37
import org .apache .lucene .index .IndexOptions ;
38
38
import org .apache .lucene .index .IndexableField ;
39
39
import org .apache .lucene .index .IndexableFieldType ;
40
+ import org .apache .lucene .index .LeafReader ;
41
+ import org .apache .lucene .index .SortedNumericDocValues ;
42
+ import org .apache .lucene .index .SortedSetDocValues ;
40
43
import org .apache .lucene .index .StoredFieldVisitor ;
41
44
import org .apache .lucene .index .Term ;
42
45
import org .apache .lucene .index .VectorEncoding ;
43
46
import org .apache .lucene .index .VectorSimilarityFunction ;
47
+ import org .apache .lucene .util .BytesRef ;
44
48
import org .opensearch .OpenSearchException ;
45
49
import org .opensearch .common .Nullable ;
46
50
import org .opensearch .common .annotation .PublicApi ;
51
55
import org .opensearch .common .metrics .CounterMetric ;
52
56
import org .opensearch .common .metrics .MeanMetric ;
53
57
import org .opensearch .common .util .set .Sets ;
58
+ import org .opensearch .common .xcontent .XContentFactory ;
54
59
import org .opensearch .common .xcontent .XContentHelper ;
55
60
import org .opensearch .common .xcontent .XContentType ;
56
61
import org .opensearch .common .xcontent .support .XContentMapValues ;
57
62
import org .opensearch .core .common .bytes .BytesReference ;
58
63
import org .opensearch .core .xcontent .MediaTypeRegistry ;
64
+ import org .opensearch .core .xcontent .XContentBuilder ;
59
65
import org .opensearch .index .IndexSettings ;
60
66
import org .opensearch .index .VersionType ;
61
67
import org .opensearch .index .engine .Engine ;
62
68
import org .opensearch .index .engine .TranslogLeafReader ;
69
+ import org .opensearch .index .fielddata .LeafNumericFieldData ;
70
+ import org .opensearch .index .fielddata .SortedNumericDoubleValues ;
63
71
import org .opensearch .index .fieldvisitor .CustomFieldsVisitor ;
64
72
import org .opensearch .index .fieldvisitor .FieldsVisitor ;
65
73
import org .opensearch .index .mapper .DocumentMapper ;
74
+ import org .opensearch .index .mapper .FieldMapper ;
66
75
import org .opensearch .index .mapper .IdFieldMapper ;
67
76
import org .opensearch .index .mapper .Mapper ;
68
77
import org .opensearch .index .mapper .MapperService ;
78
+ import org .opensearch .index .mapper .MetadataFieldMapper ;
79
+ import org .opensearch .index .mapper .NumberFieldMapper ;
69
80
import org .opensearch .index .mapper .ParsedDocument ;
70
81
import org .opensearch .index .mapper .RoutingFieldMapper ;
71
82
import org .opensearch .index .mapper .SourceFieldMapper ;
72
83
import org .opensearch .index .mapper .SourceToParse ;
73
84
import org .opensearch .index .mapper .Uid ;
74
85
import org .opensearch .index .shard .AbstractIndexShardComponent ;
75
86
import org .opensearch .index .shard .IndexShard ;
87
+ import org .opensearch .search .DocValueFormat ;
76
88
import org .opensearch .search .fetch .subphase .FetchSourceContext ;
77
89
78
90
import java .io .IOException ;
91
+ import java .util .Arrays ;
79
92
import java .util .Collections ;
80
93
import java .util .HashMap ;
81
94
import java .util .List ;
82
95
import java .util .Map ;
83
96
import java .util .concurrent .TimeUnit ;
97
+ import java .util .stream .Collectors ;
84
98
import java .util .stream .Stream ;
85
99
86
100
import static org .opensearch .index .seqno .SequenceNumbers .UNASSIGNED_PRIMARY_TERM ;
@@ -415,6 +429,18 @@ private GetResult innerGetLoadFromStoredFields(
415
429
}
416
430
}
417
431
432
+ try {
433
+ Map <String , Object > sourceAsMap = buildUsingDocValues (docIdAndVersion .docId , docIdAndVersion .reader , mapperService , indexShard );
434
+ sourceAsMap = unflatten (sourceAsMap );
435
+ try (XContentBuilder builder = XContentFactory .jsonBuilder ()) {
436
+ builder .map (sourceAsMap );
437
+ source = BytesReference .bytes (builder );
438
+ }
439
+ } catch (IOException ex ) {
440
+ throw new RuntimeException (ex );
441
+ }
442
+
443
+
418
444
return new GetResult (
419
445
shardId .getIndexName (),
420
446
id ,
@@ -428,11 +454,124 @@ private GetResult innerGetLoadFromStoredFields(
428
454
);
429
455
}
430
456
457
+ private static Map <String , Object > unflatten (Map <String , Object > flattened ) {
458
+ Map <String , Object > unflattened = new HashMap <>();
459
+ for (String key : flattened .keySet ()) {
460
+ doUnflatten (flattened , unflattened , key , flattened .get (key ));
461
+ }
462
+ return unflattened ;
463
+ }
464
+
465
+ private static Map <String , Object > doUnflatten (
466
+ Map <String , Object > flattened ,
467
+ Map <String , Object > unflattened ,
468
+ String key ,
469
+ Object value ) {
470
+
471
+ String [] parts = key .split ("\\ ." );
472
+ for (int i = 0 ; i < parts .length ; i ++) {
473
+ String part = parts [i ];
474
+ Object current = flattened .get (part );
475
+ if (i == (parts .length - 1 )) {
476
+ unflattened .put (part , value );
477
+ } else if (current == null ) {
478
+ if ((current = unflattened .get (part )) == null ) {
479
+ current = new HashMap <>();
480
+ }
481
+ unflattened .put (part , current );
482
+ unflattened = (Map <String , Object >) current ;
483
+ } else if (current instanceof Map ) {
484
+ unflattened .put (part , current );
485
+ unflattened = (Map <String , Object >) current ;
486
+ }
487
+ }
488
+ return unflattened ;
489
+ }
490
+
491
+
431
492
private static FieldsVisitor buildFieldsVisitors (String [] fields , FetchSourceContext fetchSourceContext ) {
432
493
if (fields == null || fields .length == 0 ) {
433
494
return fetchSourceContext .fetchSource () ? new FieldsVisitor (true ) : null ;
434
495
}
435
496
436
497
return new CustomFieldsVisitor (Sets .newHashSet (fields ), fetchSourceContext .fetchSource ());
437
498
}
499
+
500
+ private static Map <String , Object > buildUsingDocValues (int docId , LeafReader reader , MapperService mapperService , IndexShard indexShard ) throws IOException {
501
+ Map <String , Object > docValues = new HashMap <>();
502
+ for (Mapper mapper : mapperService .documentMapper ().mappers ()) {
503
+ if (mapper instanceof MetadataFieldMapper ) {
504
+ continue ;
505
+ }
506
+ mapper .name ();
507
+ if (mapper instanceof FieldMapper ) {
508
+ FieldMapper fieldMapper = (FieldMapper ) mapper ;
509
+ if (fieldMapper .fieldType ().hasDocValues ()) {
510
+ String fieldName = fieldMapper .name ();
511
+ FieldInfo fieldInfo = reader .getFieldInfos ().fieldInfo (fieldName );
512
+ DocValueFormat format = fieldMapper .fieldType ().docValueFormat (null , null );
513
+ if (fieldInfo != null ) {
514
+ switch (fieldInfo .getDocValuesType ()) {
515
+ case SORTED_SET :
516
+ SortedSetDocValues dv = reader .getSortedSetDocValues (fieldName );
517
+ if (dv .advanceExact (docId )) {
518
+ BytesRef [] values = new BytesRef [dv .docValueCount ()];
519
+ for (int i = 0 ; i < dv .docValueCount (); i ++) {
520
+ values [i ] = dv .lookupOrd (dv .nextOrd ());
521
+ }
522
+ if (values .length > 1 ) {
523
+ docValues .put (fieldName , Arrays .stream (values ).map (format ::format ).collect (Collectors .toList ()));
524
+ } else {
525
+ docValues .put (fieldName , format .format (values [0 ]));
526
+ }
527
+ }
528
+ break ;
529
+ case SORTED_NUMERIC :
530
+ SortedNumericDocValues sndv = reader .getSortedNumericDocValues (fieldName );
531
+ if (fieldMapper instanceof NumberFieldMapper ) {
532
+ NumberFieldMapper .NumberType numberType = ((NumberFieldMapper ) fieldMapper ).getType ();
533
+ switch (numberType ) {
534
+ case HALF_FLOAT :
535
+ case FLOAT :
536
+ case DOUBLE :
537
+ SortedNumericDoubleValues doubleValues = ((LeafNumericFieldData ) indexShard .indexFieldDataService ().getForField (fieldMapper .fieldType (), "" , () -> null )
538
+ .load (reader .getContext ())).getDoubleValues ();
539
+ if (doubleValues .advanceExact (docId )) {
540
+ int size = doubleValues .docValueCount ();
541
+ double [] vals = new double [size ];
542
+ for (int i = 0 ; i < size ; i ++) {
543
+ vals [i ] = doubleValues .nextValue ();
544
+ }
545
+ if (size > 1 ) {
546
+ docValues .put (fieldName , vals );
547
+ } else {
548
+ docValues .put (fieldName , vals [0 ]);
549
+ }
550
+ }
551
+ break ;
552
+ case INTEGER :
553
+ case LONG :
554
+ case UNSIGNED_LONG :
555
+ if (sndv .advanceExact (docId )) {
556
+ int size = sndv .docValueCount ();
557
+ long [] vals = new long [size ];
558
+ for (int i = 0 ; i < size ; i ++) {
559
+ vals [i ] = sndv .nextValue ();
560
+ }
561
+ if (size > 1 ) {
562
+ docValues .put (fieldName , vals );
563
+ } else {
564
+ docValues .put (fieldName , vals [0 ]);
565
+ }
566
+ }
567
+ }
568
+ }
569
+ break ;
570
+ }
571
+ }
572
+ }
573
+ }
574
+ }
575
+ return docValues ;
576
+ }
438
577
}
0 commit comments