Sorting on BigDecimal Field


#1

I have instrumentAmount as BigDecimal type field in an indexed entity which is indexed using a field bridge

@Column(name = “INSTRUMENT_AMOUNT”, precision = 24, scale = 6)
@Field(store=Store.NO,index=Index.YES,analyze=Analyze.NO)
@NumericField
@FieldBridge(impl = BigDecimalNumericFieldBridge.class)
@SortableField
private BigDecimal instrumentAmount;

public class BigDecimalNumericFieldBridge implements MetadataProvidingFieldBridge, TwoWayFieldBridge {
private static final BigDecimal storeFactor = BigDecimal.valueOf(100);

@Override
public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
	if (value != null) {
		BigDecimal decimalValue = (BigDecimal) value;
		Long indexedValue = decimalValue.multiply(storeFactor).longValue();
		luceneOptions.addNumericFieldToDocument(name, indexedValue, document);
	}
}

@Override
public Object get(String name, Document document) {
	String fromLucene = document.get(name);
	BigDecimal storedBigDecimal = new BigDecimal(fromLucene);
	return storedBigDecimal.divide(storeFactor);
}

@Override
public String objectToString(Object object) {
	return object.toString();
}

@Override
public void configureFieldMetadata(String name, FieldMetadataBuilder builder) {
	builder.field(name, FieldType.LONG);
}

}

Now, when i am trying to sort on this field using below code:
SortField sortField = new SortField( “instrumentAmount”, SortField.Type.LONG, false );
Sort sort = new Sort(sortField);

Below exception is coming:
unexpected docvalues type NONE for field ‘instrumentAmount’ (expected=NUMERIC). Use UninvertingReader or index with docvalues.

Please suggest how to sort on this field?


#2

Unfortunately, for custom bridges, the SortableField annotation is only used to validate queries, it’s ignored when indexing.

You will need to add the docvalues yourself.
Instead of this:

public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
	if (value != null) {
		BigDecimal decimalValue = (BigDecimal) value;
		Long indexedValue = decimalValue.multiply(storeFactor).longValue();
		luceneOptions.addNumericFieldToDocument(name, indexedValue, document);
	}
}

… do this:

public void set(String name, Object value, Document document, LuceneOptions luceneOptions) {
	if (value != null) {
		BigDecimal decimalValue = (BigDecimal) value;
		Long indexedValue = decimalValue.multiply(storeFactor).longValue();
		luceneOptions.addNumericFieldToDocument(name, indexedValue, document);
		luceneOptions.addNumericDocValuesFieldToDocument(name, indexedValue, document);
	}
}

#3

Thanks yrodiere for the solution, it worked