Как реализовать поиск значений int в спящем поиске? - PullRequest
0 голосов
/ 20 марта 2012

Я пытаюсь выполнить поиск целочисленного значения. Я аннотировал параметр с помощью @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 ]

3 голосов
/ 20 марта 2012

Я не смог найти документацию для 3.0.1 GA, но более новые версии Hibernate Search имеют аннотацию NumericField .

3 голосов
/ 20 марта 2012

Хорошо, я думаю, ответ на мой вопрос - 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();
    }

Тогда в моих поисках мне просто нужно использовать этот мост при создании запроса и вуаля это работает =)

Некоторые тесты с Люком:

confirmedCount:[00005 TO 00100]

name confirmedCount
g    00006
d    00019
0 голосов
/ 01 августа 2016

Если у вас есть поле строкового типа, но вы хотите отсортировать по номерам и применить к нему запрос ранга. у вас должно быть преобразовано строковое поле в числовое поле, но здесь без конвертирующего поля вы можете реализовать ранжированный запрос к полю и применить сортировку как число.

Добавить или создать собственный @FieldBridge на поле.

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

private String currentCtc;

Предположим, вы хотите искать поле currentCtc как число, но это строковое поле. Вы можете реализовать Rang Query в поле currentCtc.

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 Query к полю String, но оно работает как число.

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

Применить сортировку по строковому полю как число

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

...