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

我正在尝试实现文档索引(对应于DB行的rougly),其中一个字段是整数。 我将它们添加到索引中:

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 stored stored,indexed,tokenized,omitNorms,indexOptions=DOCS_ONLY> 

所以我的int字段存储,但没有索引。 此查询按预期工作: id_s:152 ,而此查询永远不会返回任何内容: ticket_id:152

我究竟做错了什么? 如何将这样的字段添加到索引并使其可搜索?

以下对我有用:

  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所指出的,对于数值(long,date,float等),您需要使用NumericRangeQuery并指定精度。 否则Lucene不知道你想如何定义相似性。

可以使用NumericRangeQuery查询数字字段。 要获得完全匹配,只需将max和min设置为相等的值即可。

指示字段未编入索引的输出可能是由于与文本值相比,数值的索引方式不同。 考虑到该字段被转换为Lucene的数字表示,字面值152确实不会被索引

但是,一目了然,您对id_s的处理可能是更好的选择。 ID通常不作为数值处理,而是作为恰好用数字表示的简单标识符。 如果您不需要对字段进行数字排序或范围查询,则将索引作为StringField确实更有意义。

另一个答案来自这个post(第三个答案): Lucene 4.0 IndexWriter updateDocument for Numeric Term

基本上,您使用int值创建一个Term,如下所示:

 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。