@@ -606,73 +606,77 @@ public static FieldSortBuilder getPrimaryFieldSortOrNull(SearchSourceBuilder sou
606606 }
607607
608608 /**
609- * Return the {@link MinAndMax } indexed value for shard from the provided {@link FieldSortBuilder} or <code>null</code> if unknown.
609+ * Return the {@link FieldStats } indexed value for shard from the provided {@link FieldSortBuilder} or {@link FieldStats#UNKNOWN} if unknown.
610610 * The value can be extracted on non-nested indexed mapped fields of type keyword, numeric or date, other fields
611- * and configurations return <code>null</code> .
611+ * and configurations return {@link FieldStats#UNKNOWN} .
612612 */
613- public static MinAndMax <?> getMinMaxOrNull (QueryShardContext context , FieldSortBuilder sortBuilder ) throws IOException {
613+ public static FieldStats getFieldStatsForShard (QueryShardContext context , FieldSortBuilder sortBuilder ) throws IOException {
614614 final SortAndFormats sort = SortBuilder .buildSort (Collections .singletonList (sortBuilder ), context ).get ();
615- return getMinMaxOrNullInternal (context .getIndexReader (), context , sortBuilder , sort );
615+ return getFieldStatsInternal (context .getIndexReader (), context , sortBuilder , sort );
616616 }
617617
618618 /**
619- * Return the {@link MinAndMax } indexed value for segment from the provided {@link FieldSortBuilder} or <code>null</code> if unknown.
619+ * Return the {@link FieldStats } indexed value for segment from the provided {@link FieldSortBuilder} or {@link FieldStats#UNKNOWN} if unknown.
620620 * The value can be extracted on non-nested indexed mapped fields of type keyword, numeric or date, other fields
621- * and configurations return <code>null</code> .
621+ * and configurations return {@link FieldStats#UNKNOWN} .
622622 */
623- public static MinAndMax <?> getMinMaxOrNullForSegment (
623+ public static FieldStats getFieldStatsForSegment (
624624 QueryShardContext context ,
625625 LeafReaderContext ctx ,
626626 FieldSortBuilder sortBuilder ,
627627 SortAndFormats sort
628628 ) throws IOException {
629- return getMinMaxOrNullInternal (ctx .reader (), context , sortBuilder , sort );
629+ return getFieldStatsInternal (ctx .reader (), context , sortBuilder , sort );
630630 }
631631
632- private static MinAndMax <?> getMinMaxOrNullInternal (
632+ private static FieldStats getFieldStatsInternal (
633633 IndexReader reader ,
634634 QueryShardContext context ,
635635 FieldSortBuilder sortBuilder ,
636636 SortAndFormats sort
637637 ) throws IOException {
638638 SortField sortField = sort .sort .getSort ()[0 ];
639639 if (sortField .getField () == null ) {
640- return null ;
640+ return FieldStats . UNKNOWN ;
641641 }
642642 MappedFieldType fieldType = context .fieldMapper (sortField .getField ());
643643 if (reader == null || (fieldType == null || fieldType .isSearchable () == false )) {
644- return null ;
644+ return FieldStats . UNKNOWN ;
645645 }
646646 switch (IndexSortConfig .getSortFieldType (sortField )) {
647647 case LONG :
648648 case INT :
649649 case DOUBLE :
650650 case FLOAT :
651- return extractNumericMinAndMax (reader , sortField , fieldType , sortBuilder );
651+ return extractNumericFieldStats (reader , sortField , fieldType , sortBuilder );
652652 case STRING :
653653 case STRING_VAL :
654654 if (fieldType instanceof KeywordFieldMapper .KeywordFieldType ) {
655655 Terms terms = MultiTerms .getTerms (reader , fieldType .name ());
656656 if (terms == null ) {
657- return null ;
657+ return FieldStats . UNKNOWN ;
658658 }
659- return terms .getMin () != null ? new MinAndMax <>(terms .getMin (), terms .getMax ()) : null ;
659+ MinAndMax <?> minAndMax = terms .getMin () != null ? new MinAndMax <>(terms .getMin (), terms .getMax ()) : null ;
660+ return new FieldStats (minAndMax , terms .getDocCount () == reader .maxDoc ());
660661 }
661662 break ;
662663 }
663- return null ;
664+ return FieldStats . UNKNOWN ;
664665 }
665666
666- private static MinAndMax <?> extractNumericMinAndMax (
667+ private static FieldStats extractNumericFieldStats (
667668 IndexReader reader ,
668669 SortField sortField ,
669670 MappedFieldType fieldType ,
670671 FieldSortBuilder sortBuilder
671672 ) throws IOException {
672673 String fieldName = fieldType .name ();
673- if (PointValues .size (reader , fieldName ) == 0 ) {
674- return null ;
674+ final int docCount = PointValues .getDocCount (reader , fieldName );
675+ if (docCount == 0 ) {
676+ return FieldStats .UNKNOWN ;
675677 }
678+ final boolean allDocsNonMissing = docCount == reader .maxDoc ();
679+ MinAndMax <?> minAndMax = null ;
676680 if (fieldType instanceof NumberFieldType ) {
677681 NumberFieldType numberFieldType = (NumberFieldType ) fieldType ;
678682 Number minPoint = numberFieldType .parsePoint (PointValues .getMinPackedValue (reader , fieldName ));
@@ -681,27 +685,31 @@ private static MinAndMax<?> extractNumericMinAndMax(
681685 case LONG :
682686 if (numberFieldType .numericType () == NumericType .UNSIGNED_LONG ) {
683687 // The min and max are expected to be BigInteger numbers
684- return new MinAndMax <>((BigInteger ) minPoint , (BigInteger ) maxPoint );
688+ minAndMax = new MinAndMax <>((BigInteger ) minPoint , (BigInteger ) maxPoint );
685689 } else {
686- return new MinAndMax <>(minPoint .longValue (), maxPoint .longValue ());
690+ minAndMax = new MinAndMax <>(minPoint .longValue (), maxPoint .longValue ());
687691 }
692+ break ;
688693 case INT :
689- return new MinAndMax <>(minPoint .intValue (), maxPoint .intValue ());
694+ minAndMax = new MinAndMax <>(minPoint .intValue (), maxPoint .intValue ());
695+ break ;
690696 case DOUBLE :
691- return new MinAndMax <>(minPoint .doubleValue (), maxPoint .doubleValue ());
697+ minAndMax = new MinAndMax <>(minPoint .doubleValue (), maxPoint .doubleValue ());
698+ break ;
692699 case FLOAT :
693- return new MinAndMax <>(minPoint .floatValue (), maxPoint .floatValue ());
700+ minAndMax = new MinAndMax <>(minPoint .floatValue (), maxPoint .floatValue ());
701+ break ;
694702 default :
695- return null ;
703+ // no-op
696704 }
697705 } else if (fieldType instanceof DateFieldType ) {
698706 DateFieldType dateFieldType = (DateFieldType ) fieldType ;
699707 Function <byte [], Long > dateConverter = createDateConverter (sortBuilder , dateFieldType );
700708 Long min = dateConverter .apply (PointValues .getMinPackedValue (reader , fieldName ));
701709 Long max = dateConverter .apply (PointValues .getMaxPackedValue (reader , fieldName ));
702- return new MinAndMax <>(min , max );
710+ minAndMax = new MinAndMax <>(min , max );
703711 }
704- return null ;
712+ return new FieldStats ( minAndMax , allDocsNonMissing ) ;
705713 }
706714
707715 private static Function <byte [], Long > createDateConverter (FieldSortBuilder sortBuilder , DateFieldType dateFieldType ) {
0 commit comments