我正在尝试实现文档索引(对应于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);
Run Code Online (Sandbox Code Playgroud)
看来我根本无法查询该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>>
Run Code Online (Sandbox Code Playgroud)
所以我的int字段存储,但没有索引.这个查询按预期工作:id_s:152虽然这个从不返回任何东西:ticket_id:152.
我究竟做错了什么?如何将这样的字段添加到索引并使其可搜索?
min*_*das 19
以下对我有用:
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"
Run Code Online (Sandbox Code Playgroud)
正如femtoRgon指出的那样,对于数值(longs,date,float等),你需要拥有NumericRangeQuery并指定精度.否则Lucene不知道你想如何定义相似性.
可以使用NumericRangeQuery查询数字字段.要获得完全匹配,只需将max和min设置为相等的值即可.
指示字段未编入索引的输出可能是由于与文本值相比,数值的索引方式不同.考虑到该字段被转换为Lucene的数字表示,文字值152确实不会被索引
但是,乍一看,您对id_s的处理可能是更好的选择.ID通常不作为数值处理,而是作为恰好用数字表示的简单标识符.如果您不需要对字段进行数字排序或范围查询,那么索引StringField就更有意义了.
另一个答案来自这个线程(第三个答案):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);
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用此术语进行搜索或删除/更新索引。在第一次测试中,这对我来说效果很好。然而,我不知道这是否是做事的“正确”方式。我之前使用过 NumericRangeFilter 来过滤 IntFields,但现在我倾向于使用这种方法并使用常规的 termFilter 或 TermQueries。