Java 如何在Lucene 4中搜索整型字段?
我试图实现文档索引(与DB行相对应),其中一个字段是整数。我将它们添加到索引中,如下所示:Java 如何在Lucene 4中搜索整型字段?,java,lucene,Java,Lucene,我试图实现文档索引(与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.St
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\u id
字段,而id\u s
工作正常
其中一个文档是(为了可读性,我添加了空格):
文档<
存储、索引、标记化、省略规范、indexOptions=DOCS\u
存储
存储的、索引的、标记的、省略的、索引选项=文档\u ONLY>
所以我的int字段是存储的,但没有索引。此查询按预期工作:id\u-s:152
,而此查询从不返回任何内容:ticket\u-id:152
我做错了什么?如何将这样的字段添加到索引中并使其可搜索?可以使用。要精确匹配,只需将“最大值”和“最小值”设置为相等值 指示字段未索引的输出可能是由于数值索引方式与文本值不同。考虑到字段已转换为Lucene的数字表示形式,文字值
152
实际上不会被索引
然而,乍一看,您对id的处理可能是更好的选择。ID通常不作为数值处理,而是作为碰巧用数字表示的简单标识符处理。如果您不需要对字段进行数字排序或范围查询,那么作为StringField
进行索引肯定更有意义。以下内容适合我:
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指出的,对于数值(长、日期、浮点等),您需要使用
numeriRangeQuery
并指定精度。否则,Lucene不知道如何定义相似性。另一个答案来自此线程(第三个答案):
基本上,使用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来代替。是否“234”表示相同的数据段,如果是这样,我认为在索引中存储两次是不对的,一次作为字符串,一次作为整数。
234
存储在不同的字段中(ticket\u id
和id\u s
)。我看不出这有什么问题。从概念上讲,这可能是错误的,但本示例的目的只是证明这两种技术都是可行的。
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);