根据它们在休眠搜索中表示的整数值对字符串进行排序

Sorting strings based on the integer value they represent in hibernate search

我有一个包含字符串字段的实体。

有时这个字符串字段存储实际的单词,因此根据字典顺序排序是有意义的。但是,有一个用例,该字段存储字符串值,如“0%”、“10%”、“100%”、“20%”。

默认字符串排序生成以下序列:0% 10% 100% 20%。

排序后的理想顺序是0%、10%、20%、100%(由它们所代表的百分比决定)。 保证没有混合数据,即你不会有“10%”和"word"出现在需要排序的相同序列中。

我的问题是有没有一种方法可以实现根据它们所代表的数值对字符串进行排序?

理想情况下,您应该将模型更改为具有两个字段:一个是整数类型,您将在其中保存百分比,另一个是字符串类型,您将在其中保存字符串值:

@Entity
@Indexed
public class MyEntity {

  @Field
  @SortableField
  private int percentage;

  @Field
  @SortableField
  private String notPercentage;


  // ... other properties, getters and setters ...
}

然后在排序时,您只需对两个字段进行排序。由于您确定它们是互斥的,因此对两者进行排序不是问题:

QueryBuilder queryBuilder = ...;
FullTextQuery ftQuery = ...;
ftQuery.sort(queryBuilder.sort().byField("percentage").andByField("notPercentage").createSort());

或者,如果你真的想在你的 ORM 模型中保留一个字符串 属性(每个都有他自己的......),你可以使用自定义桥对你的值应用填充,这样它们排序正确:

@Entity
@Indexed
public class MyEntity {

  @Field(bridge = @FieldBridge(impl = PaddingIfPercentageBridge.class))
  @SortableField
  private String percentageOrNot;

  // ... other properties, getters and setters ...
}

public class PaddingIfPercentageBridge implements TwoWayStringBridge {

    private static final Pattern PERCENTAGE = Pattern.compile("[0-9]+%");

    @Override
    public String objectToString(Object object) {
       if ( object == null ) {
           return null;
       }
        String string = (String) object;
       if ( !PERCENTAGE.matcher( string ).matches() ) {
           return string;
       }
        StringBuilder paddedPercentage = new StringBuilder();
        for ( int padIndex = string.length(); padIndex < 4; padIndex++ ) {
            paddedPercentage.append( '0' );
        }
        return paddedPercentage.append( string ).toString();
    }

    @Override
    public Object stringToObject(String stringValue) {
       // Ideally you should remove the padding here...
        return stringValue;
    }

}

然后您可以对单个字段进行排序:

QueryBuilder queryBuilder = ...;
FullTextQuery ftQuery = ...;
ftQuery.sort(queryBuilder.sort().byField("percentageOrNot").createSort());