11

Lucene.NET (v2.0) を使用して、Visual Basic 9 (VS2008) でデスクトップ検索エンジンを開発しています。

次のコードを使用して IndexWriter を初期化します

Private writer As IndexWriter

writer = New IndexWriter(indexDirectory, New StandardAnalyzer(), False)

writer.SetUseCompoundFile(True)

同じドキュメント フォルダ (インデックスを作成するファイルを含む) を 2 回選択すると、そのドキュメント フォルダ内のファイルごとに 2 つの異なるエントリがインデックスに作成されます。

IndexWriter で、インデックスに既に存在するファイルをすべて破棄するようにします。

これを確実にするために何をすべきですか?

4

7 に答える 7

20

Steve が述べたように、IndexReader のインスタンスを使用し、その DeleteDocuments メソッドを呼び出す必要があります。DeleteDocuments は、Term オブジェクトのインスタンスまたはドキュメントの Lucene の内部 ID のいずれかを受け入れます (通常、Lucene がセグメントをマージすると変更されるため、内部 ID を使用することはお勧めしません)。

最善の方法は、アプリケーション固有のインデックスに保存した一意の識別子を使用することです。たとえば、診療所の患者のインデックスに「patient_id」というフィールドがある場合、用語を作成し、それを引数として DeleteDocuments に渡すことができます。次の例を参照してください (申し訳ありませんが、C#):

int patientID = 12;
IndexReader indexReader = IndexReader.Open( indexDirectory );
indexReader.DeleteDocuments( new Term( "patient_id", patientID ) );

その後、IndexWriter のインスタンスを使用して、患者の記録を再度追加できます。この記事http://www.codeproject.com/KB/library/IntroducingLucene.aspxから多くのことを学びました。

お役に立てれば。

于 2009-01-28T15:41:17.553 に答える
11

id フィールドを使用した削除については、時代遅れの例がたくさんあります。以下のコードは Lucene.NET 2.4 で動作します。

既に IndexWriter を使用している場合、または IndexSearcher.Reader にアクセスする場合は、IndexReader を開く必要はありません。IndexWriter.DeleteDocuments(Term) を使用できますが、最初に id フィールドを正しく保存したことを確認するのが難しい部分です。ドキュメントを保存するときは、id フィールドのインデックス設定として Field.Index.NOT_ANALYZED を必ず使用してください。これはトークン化せずにフィールドにインデックスを付けます。これは非常に重要です。この方法で使用すると、他の Field.Index 値は機能しません。

IndexWriter writer = new IndexWriter("\MyIndexFolder", new StandardAnalyzer());
var doc = new Document();
var idField = new Field("id", "MyItemId", Field.Store.YES, Field.Index.NOT_ANALYZED);
doc.Add(idField);
writer.AddDocument(doc);
writer.Commit();

同じライターを使用して、ドキュメントを簡単に削除または更新できるようになりました。

Term idTerm = new Term("id", "MyItemId");
writer.DeleteDocuments(idTerm);
writer.Commit();
于 2010-02-02T22:58:49.573 に答える
6

lucene インデックスを更新するには、古いエントリを削除して新しいエントリを書き込む必要があります。したがって、IndexReader を使用して現在のアイテムを見つけ、writer を使用してそれを削除してから、新しいアイテムを追加する必要があります。複数のエントリについても同じことが言えます。これは、あなたがやろうとしていることだと思います。すべてのエントリを見つけて、すべて削除してから、新しいエントリを書き込んでください。

于 2009-01-24T16:27:15.380 に答える
6

インデックス内のすべてのコンテンツを削除して再入力する場合は、次のステートメントを使用できます

writer = New IndexWriter(indexDirectory, New StandardAnalyzer(), True)

IndexWriter コンストラクターの最後のパラメーターは、新しいインデックスを作成するかどうか、または新しいドキュメントを追加するために既存のインデックスを開くかどうかを決定します。

于 2009-01-24T16:30:20.630 に答える
4

以下のオプションがあり、要件に応じて使用できます。

以下のコードスナップを参照してください。[C# のソース コード、vb.net に変換してください]

Lucene.Net.Documents.Document doc = ConvertToLuceneDocument(id, data);
Lucene.Net.Store.Directory dir = Lucene.Net.Store.FSDirectory.Open(new DirectoryInfo(UpdateConfiguration.IndexTextFiles));
Lucene.Net.Analysis.Analyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
Lucene.Net.Index.IndexWriter indexWriter = new Lucene.Net.Index.IndexWriter(dir, analyzer, false, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);
Lucene.Net.Index.Term idTerm = new Lucene.Net.Index.Term("id", id);

foreach (FileInfo file in new DirectoryInfo(UpdateConfiguration.UpdatePath).EnumerateFiles())
{
        Scenario 1: Single step update.
                indexWriter.UpdateDocument(idTerm, doc, analyzer);

        Scenario 2: Delete a document and then Update the document
                indexWriter.DeleteDocuments(idTerm);
                indexWriter.AddDocument(doc);

        Scenario 3: Take necessary steps if a document does not exist.

            Lucene.Net.Index.IndexReader iReader = Lucene.Net.Index.IndexReader.Open(indexWriter.GetDirectory(), true);
            Lucene.Net.Search.IndexSearcher iSearcher = new Lucene.Net.Search.IndexSearcher(iReader);
            int docCount = iSearcher.DocFreq(idTerm);
            iSearcher.Close();
            iReader.Close();
            if (docCount == 0)
            {
                    //TODO: Take necessary steps
                    //Possible Step 1: add document
                    //indexWriter.AddDocument(doc);

                    //Possible Step 2: raise the error for the unknown document
            }
}
indexWriter.Optimize();
indexWriter.Close();
于 2011-10-25T07:28:53.967 に答える
3

少数のドキュメント (たとえば、全体の 10% 未満) のみを変更する場合を除き、ゼロからインデックスを再作成する方がほぼ確実に高速です (マイレージは、保存された/インデックス付けされたフィールドなどによって異なる場合があります)。

そうは言っても、私は常に一時ディレクトリにインデックスを作成し、完了したら新しいディレクトリを所定の位置に移動します。そうすれば、インデックスの作成中にダウンタイムがほとんどなく、何か問題が発生した場合でも、良好なインデックスを維持できます。

于 2009-02-10T13:57:20.687 に答える
2

もちろん、1 つのオプションは、ドキュメントを削除してから、ドキュメントの更新バージョンを追加することです。

または、IndexWriter クラスの UpdateDocument() メソッドを使用することもできます。

writer.UpdateDocument(new Term("patient_id", document.Get("patient_id")), document);

もちろん、これには、更新するドキュメント (この例では「patient_id」) を見つけることができるメカニズムが必要です。

より完全なソース コードの例をブログに掲載しました。

于 2010-07-31T05:26:34.807 に答える