Lucene は、.NET での全文検索をサポートする効率的で強力な検索エンジンです。 テキスト検索を簡単にし、豊富な API セットを提供して、高速で使いやすいテキスト検索手法を提供します。
さらに、Lucene が提供しないものが XNUMX つあります。それはスケーラビリティです。 Lucene アプリケーションは通常、データをファイルに書き込み、ディスクに保存するため、大量のメモリ割り当てが発生します。 NCache 提供 分散Lucene Lucene アプリケーションをスケーラブルかつ分散型にする機能。 また、単一障害点の問題に対する、直線的に拡張可能な分散型の代替手段も提供します。
NCache 詳細 分散 Lucene の仕組み 分散Luceneドキュメント
Distributed Lucene の詳細については、それが機能しており、なぜこれが頼りになるオプションなのかについては、こちらをご覧ください。 分散 Lucene: スケーラビリティのための .NET での全文検索. Distributed Lucene の詳細に入る前に、基本的なワークフローを示す Distributed Lucene ソリューションをざっと見てみましょう。
以下のコード サンプルは、主にこれら XNUMX つの手順を実行する分散 Lucene を示しています。
- を初期化する NCache ディレクトリ。
- 検索を実行するためにドキュメントにインデックスを付けます。
- 索引付けされたドキュメントで検索を実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
{ // Specify the cache name that is used for Lucene string cache = "LuceneCache"; // Specify the index name to create the indexes string indexName = "ProductIndex"; // Create a directory and open it on the cache and the index path Directory directory = NCacheDirectory.Open(cache, indexName); // Specify the analyzer used to analyze data Analyzer analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48); // Create an indexWriterConfig which holds all the configurations to create an instance of the writer IndexWriterConfig config = new IndexWriterConfig(LuceneVersion.LUCENE_48, analyzer); // Create the indexWriter with the analyzer and the configuration IndexWriter indexWriter = new IndexWriter(directory, config); // Add the products information that is to be indexed Product[] products = FetchProductsFromDB(); foreach (var prod in products) { // Create a document and add fields to it Document doc = new Document(); doc.Add(new TextField("id", prod.ProductID(), Field.Store.YES)); doc.Add(new TextField("name", prod.ProductName, Field.Store.NO)); doc.Add(new TextField("category", prod.Category, Field.Store.YES)); doc.Add(new TextField("description", prod.Description, Field.Store.YES)); // Writer is created previously indexWriter.AddDocument(doc); // Call ‘Commit’ to save the changes indexWriter.Commit(); } // Open a new reader instance IndexReader reader = indexWriter.GetReader(true); // A searcher is opened to perform searching IndexSearcher indexSearcher = new IndexSearcher(reader); // Specify the searchTerm and the fieldName string searchTerm = "Beverages"; string fieldName = "Category"; LuceneVersion version = LuceneVersion.LUCENE_48; // Create a query parser and parse the query with the parser // Analyzer is whitespace analyzer as specified beforehand QueryParser parser = new QueryParser(version, fieldName, analyzer); Query query = parser.Parse(searchTerm); // Returns the top 10 hits from the result set ScoreDoc[] docsFound = indexSearcher.Search(query, 10).ScoreDocs; // Closes all the files associated with this index reader.Dispose(); } catch(Exception ex) { // Handle Lucene exceptions } |
このブログでは、全文検索のための分散Luceneの詳細な手順と作業に焦点を当てています。
NCache 詳細 分散 Lucene の仕組み Luceneコンポーネントと概要
分散Luceneに移行する方法は?
分散Luceneは、Luceneと同じように機能します。 分散Luceneを使用する主な利点のXNUMXつは、Luceneと同じAPIを提供することです。 Luceneユーザーは、単一のライナーコード変更のアドオンを使用して、必要なスケーラビリティーを得ることができます。 あなたはただ使用する必要があります NCache ディレクトリとアプリケーションは問題ありません。 ドキュメントにリストされている分散Luceneの動作とAPIの変更はほとんどありません ここ.
これらのステップを技術的な観点から詳しく見ていきましょう。
ステップ1:に接続する NCache ディレクトリ
紹介から始めましょう NCache Luceneを使用して.NETアプリケーションで。 主な手順は、ライブラリのLucene.NETNugetパッケージを次のように置き換えることです。 NCacheのNugetパッケージ。 NCache ディレクトリは、名前が示すように、インデックスをスケーラブルにするためにインデックスを格納するための基本クラスです。 Lucene.NET には、この目的のために複数のディレクトリ実装がありますが、最も一般的に使用されるのは FSDirectory です。 したがって、最初のステップは、 NCache ディレクトリ。
以下は、というキャッシュに接続するコードです 「luceneCache」 このディレクトリがすでに存在する場合は、既存のすべてのサーバーで提供されたディレクトリを開きます。 それ以外の場合は、指定された名前で新しいディレクトリを作成するだけです。
1 |
var indexDirectory = NCacheDirectory.Open("luceneCache", new DirectoryInfo("lucene-index-path")); |
これとともに、 NCache Distributed Lucene を使用するには、別の小さな手順が必要です。 任意の管理ツールを使用して、分散 Lucene を使用してキャッシュの Lucene インデックスを有効にします。 を参照してください。 この の章 NCache それを行うためのガイドラインのドキュメント。
Luceneのセットアップ エンタープライズ検索用の分散Lucene 分散Luceneドキュメント
ステップ2:で分散Luceneインデックスを作成する NCache
さてその NCache Luceneアプリケーションに組み込まれ、データ書き込みフェーズが始まります。 前に説明したように、Luceneはレコードをインデックスの形式でインデックス付けします。 これらのインデックスはノード上で個別に維持され、線形スケーラビリティを提供します。 キャッシュノード間のドキュメントの配布は、によって自動的に処理されます。 NCache.
ドキュメントは、キーと値のペアであるフィールドから形成されます。 各フィールドには、ユーザーが検索できるようにするテキストが含まれています。 フィールドのコンストラクターの他の部分には、個々のフィールドを処理するための命令が含まれています。
これらのドキュメントはに保存されます NCache Lucene の逆インデックス形式のディレクトリ。 Lucene はテキストをトークンの形で分解します。 インデックス作成のためにテキストを分解するこのプロセスは、アナライザーを使用して行われます。 などの複数のタイプのアナライザーがあります。 ホワイトスペースアナライザー or 標準アナライザー. このデータのトークン化は、アナライザーの主な目的がノイズ ワードを削除し、検索が実行される残りのデータにインデックスを付けることであるため、データ検索の高速化に役立ちます。 アナライザーの完全な知識については、このページを参照してください。
ドキュメントは、IndexWriter を使用してディレクトリ内でインデックス付けされます。 IndexWriter は、キャッシュに対するすべての書き込み操作の実行を担当します。 より正確には、FieldStore などの他のフィールド プロパティを追加して、検索を効率化することができます。 以下のコードは、ドキュメントを (一括して) キャッシュに書き込み、その結果、すべてのキャッシュ サーバーでインデックスを作成する方法を詳しく説明しています。 すべての書き込み操作の後に必ず Commit を呼び出してください。そうしないと、検索を実行するために操作が記録されません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public int AddDocuments () { var analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48); var writerConfig = new IndexWriterConfig (LuceneVersion.LUCENE_48, analyzer); var indexWriter = new IndexWriter (indexDirectory, writerConfig); var docCount = 0; // Fetching repository info from data source using (var enumerator = dataProvider.GetProductFTSEnumerator ()) { while (enumerator.MoveNext ()) { docs.Add (enumerator.Current.GetLuceneDocument ()); docCount++; // Perform commit after the chunk of code if (docs.Count == BULK_SIZE) { indexWriter.AddDocuments (docs); //Flush and make it ready for search indexWriter.Commit (); docs.Clear (); //Remove the added documents } } } // Return the count of added documents return docCount; } |
NCache 詳細 分散 Lucene の仕組み 分散 Lucene の地理空間インデックス
ステップ3:スケーラビリティを備えたデータの全文検索
分散Luceneを使用してキャッシュ内のデータを検索する実際のタスクは、このステップで行われます。 データのインデックス作成と同様に、読み取りもキャッシュのすべてのノードで実行され、検索結果は最終的にマージされます。 これにより、読み取りのスケーラビリティも向上し、検索が高速化されます。
LuceneのIndexWriterと同様に、 インデックスサーチャー これは、検索に基づいてデータ読み取り操作を実行するためのすべての面倒な作業を行います。 IndexSearcher はアナライザーを渡します。以前にデータの書き込みに使用したものと同じアナライザーを検索に使用することを強くお勧めします。そうしないと、結果に一貫性がなくなります。
Lucene が検索を実行するために次に使用するのは、 クエリ. Lucene には、必要に応じて、Lucene 固有の構文とともにさまざまな組み込みクエリ クラスがあります。 これらのクエリにより、検索が非常に効率的になります。たとえば、ワイルドカードを使用して検索を実行し、それに応じて検索結果をレンダリングするワイルドカード クエリがあります。 その他のクエリ タイプには、TermQuery、BooleanQuery、および SpanQuery があります。
検索結果はヒットの形式で返されます。これは、実行された検索の結果として返されるドキュメントのリストです。 次に、これらのヒットを繰り返して、クエリに一致する実際のドキュメントを取得できます。
以下に示すコードは、Luceneインデックスで実行される検索を確認するのに役立ちます。 IndexSearcherは、結果をフェッチするためにIndexReaderを使用します。 クエリは、インデックス付きデータに対して実際の検索を実行するために使用されます。 QueryParserは、アナライザーと検索語に従ってユーザー提供のテキストクエリを解析し、結果はTopDocsの形式で返されます。
以下の例では、QueryWrapperFilterが製品のカテゴリに適用され、検索結果が関連性によってソートされています。 クエリは、すべての用語にあいまいさを適用して、最適な結果を提供します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public Tuple<long, List<RepositoryInfo>> Search (string searchTerm, int top = 100, string category = null) { long totalHints = 0; var repoList = new List<ProductFTS> (); // Now create the IndexSearcher instance to search the data // directoryReader is the IndexReader instance which uses the IndexWriter var searcher = new IndexSearcher (directoryReader); try { TopDocs topDocs = null; var queryParser = new MultiFieldQueryParser (Version, Fields, analyzer); var query = new BooleanQuery (); // Split the search term into multiple search words to make fuzzy query string[] terms = searchTerm.Split (new [] { " " }, StringSplitOptions.RemoveEmptyEntries); foreach (string term in terms) query.Add (queryParser.Parse (term.Replace ("~", "") + "~"), Occur.MUST); // remove the duplicate ~, if already exits if (!string.IsNullOrEmpty (category)) { var filter = new QueryWrapperFilter (new TermQuery (new Term (CATEGORY_FIELD, category))); // Performs the search based on the filter applied topDocs = searcher.Search (query, filter, top, Sort.RELEVANCE); } else { topDocs = searcher.Search (query, top, sort : Sort.RELEVANCE); } totalHits = topDocs.TotalHits; repoList = GetSearchedDocs (searcher, topDocs); } return new Tuple<long, List<ProductFTS>> (totalHits, repoList); } |
次に、ビジネスロジックを実装して、ヒットからの検索結果を繰り返すことができます。
まとめ
Lucene は、データに対して全文検索を実行するための非常に効率的な検索エンジンですが、スケーラビリティに欠けています。 NCache Luceneと一緒に使用すると、わずかな労力でスケーラブルにできます。 スケーラブルな分散Luceneを使用すると、アプリケーションが高速になるだけでなく、単一障害点の大きな後退に対処するのにも役立ちます。 NCache XNUMX行のコード変更で.NETアプリケーションに簡単にプラグインできるため、スケーラブルなLuceneアプリケーションに最適なオプションと考えてください。