如何在hibernate搜索中实现搜索int值?

时间:2012-03-20 14:23:40

标签: java lucene hibernate-search luke

我试图搜索整数值。 我用这样的@Field注释了这个参数:

@Field(name = "confirmedCount", index = UN_TOKENIZED, store = Store.YES)
public int getConfirmedCount() {
   return stuff.size();
}

然后我用luke执行范围搜索:

confirmedCount:[5 TO 100]

我回来的结果是空的。 然后我尝试:

confirmedCount:[1 TO 2]

结果是:

name confirmedCount
b    1
a    1
d    19
c    2

所以我的问题是:为什么我得到这个回复,我该如何解决? 我使用hibernate search 3.0.1.GA

3 个答案:

答案 0 :(得分:3)

好吧我想我的问题的答案是RTFM!文件明确指出:

  

将数字转换为字符串表示形式。注意   Lucene(即用于远程查询)无法比较数字   盒子:它们必须填充

所以我们需要实现一个类桥:

public class PaddedIntegerBridge implements StringBridge {

    private int PADDING = 5;

    public String objectToString(Object object) {
        String rawInteger = ( (Integer) object ).toString();
        if (rawInteger.length() > PADDING)
            throw new IllegalArgumentException( "Try to pad on a number too big" );
        StringBuilder paddedInteger = new StringBuilder( );
        for ( int padIndex = rawInteger.length() ; padIndex < PADDING ; padIndex++ ) {
            paddedInteger.append('0');
        }
        return paddedInteger.append( rawInteger ).toString();
    }
}

然后我们需要注释该字段以便它被索引:

@Field(name = "confirmedCount", index = UN_TOKENIZED, store = Store.YES, bridge = @FieldBridge(impl = PaddedIntegerBridge.class))
    public int getConfirmedCount() {
        return stuff.size();
    }

然后在我的搜索中,我只需要在创建查询时使用这个桥,瞧 它起作用=)

Luke的一些测试:

confirmedCount:[00005 TO 00100]

name confirmedCount
g    00006
d    00019

答案 1 :(得分:3)

我找不到3.0.1 GA的文档,但是较新版本的Hibernate Search有NumericField annotation

答案 2 :(得分:0)

如果您有字符串类型字段,但您希望按数字排序并对其应用rang查询。你必须将字符串字段转换为数字字段,但是在没有转换字段的情况下,您可以在字段上实现范围查询并应用排序,如数字。

在字段上添加或创建自定义@FieldBridge。

@Field(index=Index.YES,analyze=Analyze.NO,store=Store.YES) @FieldBridge(impl=StringToNumberBridge.class)

private String currentCtc;

假设您要将currentCtc字段搜索为数字,但是它的字符串字段。您可以在currentCtc字段上实现Rang Query。

public class StringToNumberBridge implements TwoWayStringBridge {

    Logger logger=Logger.getLogger(StringToNumberBridge.class);
    public static String PADDING_PROPERTY = "padding";
    private int padding = 7; //default

    public String objectToString(Object object) {

        try {
            if(object!=null) 
            {
                String rawInteger = ((String) object).toString();
                String decimalPoint="";

                if(rawInteger.matches("\\d*\\.\\d+")) 
                {
                    decimalPoint=rawInteger.substring(rawInteger.indexOf("."));
                    rawInteger=rawInteger.substring(0,rawInteger.indexOf("."));
                    System.out.println(decimalPoint);
                    System.out.println(rawInteger);
                }
                if (rawInteger.length() > padding)
                    throw new IllegalArgumentException("Try to pad on a number too big");

                StringBuilder paddedInteger = new StringBuilder();
                for (int padIndex = rawInteger.length(); padIndex < padding; padIndex++) 
                {
                    paddedInteger.append('0');
                }
                return paddedInteger.append(rawInteger).append(decimalPoint).toString();
            }
            else {
                return "";
            }
            //return object.toString();
        } 
        catch (Exception e) {
            logger.error("NumberFormateException:::::::::::"+e);
            return null;
        }
    }

    public Object stringToObject(String stringValue) {
        return Double.valueOf(stringValue);
    }
}

您的索引字符串字段的填充与数字相同。 在字符串字段上应用Rang查询,但它的工作方式与数字相同。

booleanQuery.must(qb.range().onField("currentCtc").below(25000).createQuery());

在字符串字段上应用排序作为数字

SortField field = new SortField("currentCtc".trim(), SortField.DOUBLE,true);