17

フィールドの 1 つが整数であるドキュメントのインデックス (おおよそ 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.Store.YES));
doc.add(new StringField("id_s", rs.getString("ticket_id"),
        Field.Store.YES));
w.addDocument(doc);

ticket_id正常に動作している間、フィールドをまったくクエリできないようですid_s

ドキュメントの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

私は何を間違っていますか?このようなフィールドをインデックスに追加して検索可能にするにはどうすればよいですか?

4

3 に答える 3

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"

femtoRgon が指摘したように、数値 (long、dates、float など) についてはNumericRangeQuery、精度を取得して指定する必要があります。そうしないと、Lucene は類似性をどのように定義したいかわかりません。

于 2012-12-28T22:10:30.670 に答える
8

別の答えはこのスレッドから来ています (3 番目の答え): 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);

次に、この用語を使用してインデックスを検索したり、削除/更新したりできます。最初のテストでは、これはうまくいきました。ただし、これが「正しい」方法であるかどうかはわかりません。以前は IntField のフィルタリングに NumericRangeFilter を使用していましたが、現在はこのアプローチを使用して、代わりに通常の TermsFilter または TermQueries を使用する傾向があります。

于 2013-02-15T09:56:17.997 に答える
7

数値フィールドはNumericRangeQueryでクエリできます。完全に一致させるには、最大値と最小値を同じ値に設定します。

フィールドがインデックス付けされていないことを示す出力は、テキスト値と比較して、数値のインデックス付け方法の違いが原因である可能性があります。フィールドが Lucene の数値表現に変換されることを考慮すると、リテラル値152は実際にはインデックス化されません。

ただし、一見すると、id_s の処理がより良い代替手段である可能性があります。通常、ID は数値として扱われるのではなく、たまたま数字で表される単純な識別子として扱われます。フィールドでの数値の並べ替えや範囲クエリが必要ない場合は、 としてインデックスを作成StringFieldする方が確かに理にかなっています。

于 2012-12-28T21:42:42.080 に答える