@@ -378,7 +378,8 @@ protected static Long parseUpperRangeTerm(Object value, boolean include) {
378378
379379 private Explicit <Boolean > ignoreMalformed ;
380380 private final String nullValue ;
381- private final Long nullValueNumeric ;
381+ private final Long nullValueIndexed ; // null value to use for indexing, represented as shifted to signed long range
382+ private final Number nullValueFormatted ; // null value to use in place of a {@code null} value in the document source
382383
383384 private UnsignedLongFieldMapper (
384385 String simpleName ,
@@ -391,7 +392,15 @@ private UnsignedLongFieldMapper(
391392 ) {
392393 super (simpleName , fieldType , mappedFieldType , multiFields , copyTo );
393394 this .nullValue = nullValue ;
394- this .nullValueNumeric = nullValue == null ? null : convertToSignedLong (parseUnsignedLong (nullValue ));
395+ if (nullValue == null ) {
396+ this .nullValueIndexed = null ;
397+ this .nullValueFormatted = null ;
398+ } else {
399+ long parsed = parseUnsignedLong (nullValue );
400+ this .nullValueIndexed = convertToSignedLong (parsed );
401+ this .nullValueFormatted = parsed >= 0 ? parsed : BigInteger .valueOf (parsed ).and (BIGINTEGER_2_64_MINUS_ONE );
402+ }
403+
395404 this .ignoreMalformed = ignoreMalformed ;
396405 }
397406
@@ -410,6 +419,11 @@ protected UnsignedLongFieldMapper clone() {
410419 return (UnsignedLongFieldMapper ) super .clone ();
411420 }
412421
422+ @ Override
423+ protected Number nullValue () {
424+ return nullValueFormatted ;
425+ }
426+
413427 @ Override
414428 protected void parseCreateField (ParseContext context ) throws IOException {
415429 XContentParser parser = context .parser ();
@@ -437,7 +451,7 @@ protected void parseCreateField(ParseContext context) throws IOException {
437451 }
438452 }
439453 if (numericValue == null ) {
440- numericValue = nullValueNumeric ;
454+ numericValue = nullValueIndexed ;
441455 if (numericValue == null ) return ;
442456 } else {
443457 numericValue = convertToSignedLong (numericValue );
@@ -454,6 +468,23 @@ protected void parseCreateField(ParseContext context) throws IOException {
454468 }
455469 }
456470
471+ @ Override
472+ protected Number parseSourceValue (Object value , String format ) {
473+ if (format != null ) {
474+ throw new IllegalArgumentException ("Field [" + name () + "] of type [" + typeName () + "] doesn't support formats." );
475+ }
476+
477+ if (value .equals ("" )) {
478+ return nullValueFormatted ;
479+ }
480+ long ulValue = parseUnsignedLong (value );
481+ if (ulValue >= 0 ) {
482+ return ulValue ;
483+ } else {
484+ return BigInteger .valueOf (ulValue ).and (BIGINTEGER_2_64_MINUS_ONE );
485+ }
486+ }
487+
457488 @ Override
458489 protected void mergeOptions (FieldMapper other , List <String > conflicts ) {
459490 UnsignedLongFieldMapper mergeWith = (UnsignedLongFieldMapper ) other ;
0 commit comments