Подтвердить что ты не робот

Как искать поле int в Lucene 4?

Я пытаюсь реализовать индекс документов (грубо соответствующий строкам DB), где одно из полей является целым числом. Я добавляю их для индекса, например:

Document doc = new Document();
doc.add(new StringField("ticket_number", rs.getString("ticket_number"),
        Field.Store.YES));
doc.add(new IntField("ticket_id", rs.getInt("ticket_id"),
        Field.Store.YES));
doc.add(new StringField("id_s", rs.getString("ticket_id"),
        Field.Store.YES));
w.addDocument(doc);

Кажется, я вообще не могу запросить поле ticket_id, а id_s работает нормально.

Один из документов (я добавил пробел для чтения):

Document<
    stored,indexed,tokenized,omitNorms,indexOptions=DOCS_ONLY<ticket_number:230114W> 
    stored<ticket_id:152> 
    stored,indexed,tokenized,omitNorms,indexOptions=DOCS_ONLY<id_s:152>>

Таким образом, мое int-поле сохраняется, но не индексируется. Этот запрос работает как ожидалось: id_s:152, в то время как этот никогда ничего не возвращает: ticket_id:152.

Что я делаю неправильно? Как я могу добавить такое поле в индекс и сделать его доступным для поиска?

4b9b3361

Ответ 1

Ниже работает для меня:

    RAMDirectory idx = new RAMDirectory();
    IndexWriter writer = new IndexWriter(
            idx,
            new IndexWriterConfig(Version.LUCENE_40, new ClassicAnalyzer(Version.LUCENE_40))
    );
    Document document = new Document();
    document.add(new StringField("ticket_number", "t123", Field.Store.YES));
    document.add(new IntField("ticket_id", 234, Field.Store.YES));
    document.add(new StringField("id_s", "234", Field.Store.YES));
    writer.addDocument(document);
    writer.commit();

    IndexReader reader = DirectoryReader.open(idx);
    IndexSearcher searcher = new IndexSearcher(reader);

    Query q1 = new TermQuery(new Term("id_s", "234"));
    TopDocs td1 = searcher.search(q1, 1);
    System.out.println(td1.totalHits);  // prints "1"

    Query q2 = NumericRangeQuery.newIntRange("ticket_id", 1, 234, 234, true, true);
    TopDocs td2 = searcher.search(q2, 1);
    System.out.println(td2.totalHits);  // prints "1"

Как отметил femtoRgon, для числовых значений (длинные, даты, поплавки и т.д.) вам нужно иметь NumericRangeQuery и указать точность. В противном случае Lucene не знает, как вы хотите определить сходство.

Ответ 2

Числовые поля можно запросить с помощью NumericRangeQuery. Для точного соответствия просто установите максимальные и минимальные значения равными.

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

Однако, с одной стороны, возможно, что ваша обработка id_s может быть лучшей альтернативой. Идентификаторы обычно не обрабатываются как числовые значения, а скорее как простые идентификаторы, которые представляются цифрами. Если вам не нужна численная сортировка или запрос диапазона в поле, индексирование как StringField, безусловно, имеет больше смысла.

Ответ 3

Еще один ответ приходит из этого потока (третий ответ): Lucene 4.0 IndexWriter updateDocument для числового термина

В принципе, вы создаете термин с вашим значением int следующим образом:

String field = "myfield";
int value = 4711;
BytesRef bytes = new BytesRef(NumericUtils.BUF_SIZE_INT);
NumericUtils.intToPrefixCoded(value, 0, bytes);
Term term = new Term(field, bytes);

Затем вы можете использовать этот термин для поиска или удаления/обновления вашего индекса. В первом тесте это работало отлично для меня. Я не могу сказать, действительно ли это "правильный" способ сделать что-то. Я использовал NumericRangeFilter раньше для фильтрации IntFields, но теперь я склонен использовать этот подход и вместо этого использую обычные терминыFilter или TermQueries.