Lucene BigDecimal范围查询

时间:2020-02-25 21:27:23

标签: hibernate lucene bigdecimal hibernate-search

我在实体类上定义了以下字段:

@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类使用文档https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#example-custom-numericfieldbridge和此处的论坛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)
}

即使我执行的范围从0到999999999999(我知道它包括所有值),我在此字段上执行的所有查询都返回零结果。如果我将其保留为字符串搜索,则会出现以下错误:“包含以数字字段为目标的基于字符串的子查询”。在现场进行排序。我想念什么?预先感谢您的帮助。

修改 添加场桥逻辑:

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()
  }
}

2 个答案:

答案 0 :(得分:0)

在字段桥接逻辑的typedef函数中添加两个字段可解决此问题:

set

现在,我的搜索工作正常了。我想这使我想知道是否需要两个单独的字段定义。我认为我可以只使用一个if (value != null && (name == "test" || name == "test_sort")) { 注释,然后就不必同时存储@Fieldtest

答案 1 :(得分:0)

在字段桥逻辑的set函数中添加两个字段可解决此问题 现在我的搜索工作了。我想这使我想知道是否需要两个单独的字段定义。我想我可以只使用一个@Field注释,然后我就不需要同时存储test和test_sort。

您可能正在排序中引用字段test。如果您的排序字段名为test_sort,则在搜索查询中创建排序时必须使用该名称。

相关问题