2012-12-28 5 views
13

フィールドの1つが整数である文書のインデックス(粗くDB行に対応)を実装しようとしています。 id_sだけで正常に動作しながら、私は全くticket_idフィールドを照会することはできませんようだ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); 

:ように私は、インデックスに追加しています。

ドキュメントの1つです(私は読みやすくするために空白を追加):

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で照会できます。完全一致の場合は、maxとminを等しい値に設定するだけです。

フィールドがインデックスに登録されていないことを示す出力は、テキスト値と比較して数値のインデックス方法の違いが原因である可能性があります。フィールドが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を持っていると精度を指定する必要が数値(long型、日付、山車など)のために、指摘されたように。さもなければ、Luceneはどのように類似性を定義したいか分かりません。

+0

ありがとう、この1つは私を助けてくれました。 – SoluableNonagon

+0

'234'は同じデータを指していますか?そうであれば、インデックスに2回、ストリングとして、そしてintとして1回ストアする権利はないと思います。 –

+0

'234'は異なるフィールド(' ticket_id'と 'id_s')に格納されています。私はこれに間違ったことは何も見ません。概念的にはこれは間違っているかもしれませんが、この例の目的は両方の技術が可能であることを証明することです。 – mindas

4

別の答えこのスレッド(第3の答え)から来ている:そして、あなたは検索のため、この用語を使用することができます

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); 

、または:基本的に、あなたはこのようなあなたのint型の値でタームを作成Lucene 4.0 IndexWriter updateDocument for Numeric Term

インデックスの削除/更新最初のテストでは、これは私のためにうまくいった。しかし、これが「正しい」方法であるかどうかはわかりません。私はIntFieldsをフィルタリングするためにNumericRangeFilterを使用しましたが、今ではこのアプローチを使用して、代わりに通常のTermsFilterまたはTermQueriesを使用します。

関連する問題