如何在Lucene 4中搜索int字段?

2022-09-03 00:13:00

我正在尝试实现文档索引(与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_idid_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:152ticket_id:152

我做错了什么?如何将此类字段添加到索引并使其可搜索?


答案 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所指出的,对于数值(长整型、日期、浮点数等),您需要具有并指定精度。否则,Lucene不知道你想如何定义相似性。NumericRangeQuery


答案 2

另一个答案来自这个线程(第三个答案):Lucene 4.0 IndexWriter update数字术语文档

基本上,您使用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,但现在我倾向于使用这种方法,而是使用常规的 TermsFilter 或 TermQueries。


推荐