2012-12-28 24 views
13

我想實現一個文件索引(rougly對應於數據庫行),其中一個字段是一個整數。我將它們添加到索引,如:如何在Lucene 4中搜索int字段?

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

我在做什麼錯?我如何將這樣的字段添加到索引並使其可搜索?

回答

7

可以用NumericRangeQuery查詢數字字段。對於完全匹配,只需將最大值和最小值設置爲相等的值即可。

您的輸出指示該字段未被編入索引可能是由於數字值與文本值相比的差異。考慮到該字段被轉換爲Lucene的數字表示,文字值152確實不會被編入索引

但是,您可能一眼就看出,處理id_s可能是更好的選擇。 ID通常不是作爲數字值來處理,而是作爲恰好用數字表示的簡單標識符來處理。如果您不需要在字段中進行數字排序或範圍查詢,那麼將索引編制爲StringField當然更有意義。

18

下面爲我工作:

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不知道你想如何定義相似性。

+0

謝謝你,這個幫了我很多。 – SoluableNonagon

+0

'234'是否表示同一條數據,如果是這樣,我不認爲它有權將它存儲在索引中兩次,一次作爲一個字符串,一次作爲int。 –

+0

'234'與不同的字段('ticket_id'和'id_s')一起存儲。我看不出有什麼問題。從概念上講,這可能是錯誤的,但這個例子的目的僅僅是證明兩種技術都是可能的。 – mindas

4

另一個答案來源於此線程(第三個答案):Lucene 4.0 IndexWriter updateDocument for Numeric Term

基本上,你創建一個期限,像這樣的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。