Lucene BigDecimal 范围查询
Lucene BigDecimal Range Query
我在我的实体上定义了以下字段 class:
@Column
@FieldBridge(impl = BigDecimalNumericFieldBridge.class)
@Fields(
@Field(),
@Field(name = "test_sort", analyze = Analyze.NO, store = Store.NO, index = Index.NO))
@NumericField
@SortableField(forField = "test_sort")
val test: BigDecimal
我的 BigDecimalNumericFieldBridge class 使用文档中描述的实现:https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#example-custom-numericfieldbridge and in the forums here: https://discourse.hibernate.org/t/sorting-on-bigdecimal-field/2339
我正在使用自定义查询解析器将查询转换为数字范围查询,如下所示:
override fun newRangeQuery(field: String, part1: String, part2: String, startInclusive: Boolean, endInclusive: Boolean) {
if ("test" == field) {
val convertedPart1 = BigDecimal(part1).multiply(storeFactor).longValueExact()
val convertedPart2 = BigDecimal(part2).multiply(storeFactor).longValueExact()
return NumericRangeQuery.newLongRange(field, convertedPart1, convertedPart2, startInclusive, endInclusive)
}
return super.newRangeQuery(field, part1, part2, startInclusive, endInclusive)
}
我在该字段上执行的所有查询 return 结果为零,即使我执行从 0 到 999999999999 的范围,我知道这包括所有值。如果我将其保留为字符串搜索,则会收到以下错误:"contains a string based sub query which targets the numeric field"。对现场工作进行排序。我错过了什么?预先感谢您的帮助。
编辑
添加现场桥接逻辑:
class BigDecimalNumericFieldBridge : TwoWayFieldBridge {
override fun get(name: String, document: Document): Any? {
val fromLucene: String = document.get(name) ?: ""
if (fromLucene.isNotBlank()) {
return fromLucene.toBigDecimal().divide(LUCENE_BIG_DECIMAL_STORE_FACTOR)
}
return null
}
override fun set(name: String, value: Any?, document: Document, options: LuceneOptions) {
if (value != null && name == "test_sort") {
val decimalValue: BigDecimal = value as BigDecimal
val indexedValue: Long = decimalValue
.multiply(LUCENE_BIG_DECIMAL_STORE_FACTOR)
.longValueExact()
options.addNumericFieldToDocument(name, indexedValue, document)
options.addNumericDocValuesFieldToDocument(name, indexedValue, document)
}
}
override fun objectToString(obj: Any?): String {
return obj.toString()
}
}
在字段桥接逻辑的 set
函数中添加两个字段解决了问题:
if (value != null && (name == "test" || name == "test_sort")) {
现在我的搜索有效了。我想这让我想知道我是否需要两个单独的字段定义。我想我可以只使用一个 @Field
注释,然后我就不需要同时存储 test
和 test_sort
.
Adding both fields in the set function of the field bridge logic fixes the problem
Now my searches work. I guess that makes me wonder if I need the two separate field definitions. I think I could get away with just the one @Field annotation and then I wouldn't need to store both test and test_sort.
您可能在排序中引用了字段 test
。如果您的排序字段名为 test_sort
,则在搜索查询中创建排序时必须使用该名称。
我在我的实体上定义了以下字段 class:
@Column
@FieldBridge(impl = BigDecimalNumericFieldBridge.class)
@Fields(
@Field(),
@Field(name = "test_sort", analyze = Analyze.NO, store = Store.NO, index = Index.NO))
@NumericField
@SortableField(forField = "test_sort")
val test: BigDecimal
我的 BigDecimalNumericFieldBridge class 使用文档中描述的实现:https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#example-custom-numericfieldbridge and in the forums here: https://discourse.hibernate.org/t/sorting-on-bigdecimal-field/2339
我正在使用自定义查询解析器将查询转换为数字范围查询,如下所示:
override fun newRangeQuery(field: String, part1: String, part2: String, startInclusive: Boolean, endInclusive: Boolean) {
if ("test" == field) {
val convertedPart1 = BigDecimal(part1).multiply(storeFactor).longValueExact()
val convertedPart2 = BigDecimal(part2).multiply(storeFactor).longValueExact()
return NumericRangeQuery.newLongRange(field, convertedPart1, convertedPart2, startInclusive, endInclusive)
}
return super.newRangeQuery(field, part1, part2, startInclusive, endInclusive)
}
我在该字段上执行的所有查询 return 结果为零,即使我执行从 0 到 999999999999 的范围,我知道这包括所有值。如果我将其保留为字符串搜索,则会收到以下错误:"contains a string based sub query which targets the numeric field"。对现场工作进行排序。我错过了什么?预先感谢您的帮助。
编辑 添加现场桥接逻辑:
class BigDecimalNumericFieldBridge : TwoWayFieldBridge {
override fun get(name: String, document: Document): Any? {
val fromLucene: String = document.get(name) ?: ""
if (fromLucene.isNotBlank()) {
return fromLucene.toBigDecimal().divide(LUCENE_BIG_DECIMAL_STORE_FACTOR)
}
return null
}
override fun set(name: String, value: Any?, document: Document, options: LuceneOptions) {
if (value != null && name == "test_sort") {
val decimalValue: BigDecimal = value as BigDecimal
val indexedValue: Long = decimalValue
.multiply(LUCENE_BIG_DECIMAL_STORE_FACTOR)
.longValueExact()
options.addNumericFieldToDocument(name, indexedValue, document)
options.addNumericDocValuesFieldToDocument(name, indexedValue, document)
}
}
override fun objectToString(obj: Any?): String {
return obj.toString()
}
}
在字段桥接逻辑的 set
函数中添加两个字段解决了问题:
if (value != null && (name == "test" || name == "test_sort")) {
现在我的搜索有效了。我想这让我想知道我是否需要两个单独的字段定义。我想我可以只使用一个 @Field
注释,然后我就不需要同时存储 test
和 test_sort
.
Adding both fields in the set function of the field bridge logic fixes the problem Now my searches work. I guess that makes me wonder if I need the two separate field definitions. I think I could get away with just the one @Field annotation and then I wouldn't need to store both test and test_sort.
您可能在排序中引用了字段 test
。如果您的排序字段名为 test_sort
,则在搜索查询中创建排序时必须使用该名称。