私が働いている e コマース サイトでは、Solr を使用して製品カタログのファセットと検索を高速化しています。(Solr マニア以外の用語で言えば、これは、Zappos、Amazon、 NewEgg、および Lowe's.)
これは、Solr がこの種のことを迅速かつ適切に実行するように設計されているためです。従来のリレーショナル データベースでこの種のことを効率的に実行しようとしても、データベースでインデックスの追加と削除を開始したくない場合を除き、うまくいきません。飛んで完全なEAVに行きます。これは、Magentoの咳が愚かな咳です。したがって、SQL Server データベースは「信頼できる」データ ストアであり、Solr インデックスはそのデータの読み取り専用の「投影」です。
あなたは似たような状況にあるように聞こえるので、ここまで私と一緒にいます。次のステップは、Solr インデックスのデータが少し古くても問題ないかどうかを判断することです。あなたはおそらくそれがいくぶん古くなるという事実を受け入れたでしょうが、次の決定は
- 古すぎるのはどのくらい古くなっていますか?
- 古さよりも速度やクエリ機能を重視するのはいつですか?
たとえば、"Worker" と呼んでいるものがあります。これは、Quartz.NETを使用して C#IJob
実装を定期的に実行する Windows サービスです。3 時間ごとに実行されるこれらのジョブの 1 つが であり、そのジョブが行うのはへRefreshSolrIndexesJob
の ping だけです。これは、Solr の組み込みDataImportHandlerを使用して、実際に SQL データベースからデータを吸い込むためです。ジョブは、同期を機能させるために定期的にその URL に「触れる」必要があります。DataImportHandler は定期的に変更をコミットするため、これはすべて事実上バックグラウンドで実行され、Web サイトのユーザーには透過的です。HttpWebRequest
http://solr.example.com/dataimport?command=full-import
これは、製品カタログの情報が最大 3 時間古い可能性があることを意味します。ユーザーは、カタログ ページで「Medium In Stock (3)」のリンクをクリックしても (この種のファセット データは SOLR をクエリすることによって生成されるため)、製品の詳細ページに在庫のない媒体が表示される場合があります (これ以降)。ページ、数量情報はキャッシュされず、データベースに対して直接照会されない数少ない情報の 1 つです)。これは面倒ですが、私たちの特定のシナリオでは一般的にまれです (私たちはかなり小規模なビジネスであり、トラフィックがそれほど多くありません)。インデックス全体を最初から再構築すると、とにかく 3 時間で修正されるため、これを受け入れました。合理的なトレードオフとして。
この程度の「古さ」を受け入れることができる場合は、このバックグラウンド ワーカー プロセスを使用することをお勧めします。「数時間ごとにすべてを再構築する」アプローチを採用するか、リポジトリで ID をテーブルに挿入し、たとえばdbo.IdentitiesOfStuffThatNeedsUpdatingInSolr
.データセットのサイズや複雑さを考えると、インデックス全体を定期的にゼロから作成することは合理的ではありません。
3 番目のアプローチは、現在のドキュメントに関して Solr インデックスをほぼ同時に更新するバックグラウンド スレッドをリポジトリに生成させることです。そのため、データは数秒間だけ古くなります。
class MyRepository
{
void Save(Post post)
{
// the following method runs on the current thread
SaveThePostInTheSqlDatabaseSynchronously(post);
// the following method spawns a new thread, task,
// queueuserworkitem, whatevever floats our boat this week,
// and so returns immediately
UpdateTheDocumentInTheSolrIndexAsynchronously(post);
}
}
しかし、これが何らかの理由で爆発した場合、Solr の更新を見逃す可能性があるため、Solr に定期的に「すべてを吹き飛ばしてリフレッシュ」させるか、アウトをチェックするリーパー バックグラウンド ワーカー タイプのサービスを用意することをお勧めします。誰もが青月に一度、Solr の最新データ。
このデータを Solr からクエリする場合、いくつかの方法があります。1 つは、リポジトリのメソッドを介して Solr が完全に存在するという事実を隠すことです。Solr スキーマは、そのデータにアクセスする UI に合わせて恥知らずに調整される可能性があるため、個人的にはお勧めしません。Solr を使用して情報の簡単なファセット、並べ替え、および高速表示を提供することを既に決定しているため、Solr を最大限に使用することもできます。これは、Solr にアクセスするとき、およびキャッシュされていない最新のデータベース オブジェクトにアクセスするときに、コードで明示的にすることを意味します。
私の場合、NHibernate を使用して CRUD アクセスを行い ( ItemGroup
.すでにデータベースを抽象化しています。(これは個人的な選択です。)
しかし、データをクエリするとき、それをカタログ指向の目的で使用しているか (速度とクエリを気にする)、バックエンド管理アプリケーションのテーブルに表示するために使用しているか (通貨を気にする)をよく知っています。Web サイトでクエリを実行するために、私は というインターフェースを持っていますICatalogSearchQuery
。いくつかのパラメーター (選択したファセット、検索用語、ページ番号、ページごとのアイテム数など) を定義するメソッドを受け取り、残りのファセットSearch()
、結果の数、この結果を返すメソッドがあります。ページなどかなり退屈なもの。SearchRequest
SearchResult
興味深いのは、その実装がその下の s のICatalogSearchQuery
リストを使用していることです。ICatalogSearchStrategy
デフォルトの戦略である はSolrCatalogSearchStrategy
、単純な昔ながらの方法HttpWebRequest
で XML を解析してSOLR に直接ヒットしますHttpWebResponse
(これは、一部の SOLR クライアント ライブラリよりもはるかに使いやすく、私見ですが、私が最後に見たときから改善されている可能性があります)。それらは1年以上前です)。その戦略が何らかの理由で例外をスローしたり吐いたりするとDatabaseCatalogSearchStrategy
、SQL データベースに直接ヒットしますが、一部のパラメーターは無視されます。SearchRequest
、ファセットや高度なテキスト検索など、そこで行うのは非効率的であり、そもそも Solr を使用している理由のすべてです。アイデアは、通常、SOLR はフル機能の栄光で私の検索要求に迅速に応答するというものですが、何かが爆発して SOLR がダウンした場合でも、サイトのカタログ ページは、データベースに制限された機能セットを直接。(これが検索であることをコードで明示しているため、その戦略では、クライアントに深刻な影響を与えることを心配することなく、いくつかの検索パラメーターを無視することでいくらか自由を取ることができます。)
重要なポイント:重要なのは、古くなった可能性のあるデータ ストアに対してクエリを実行するか、信頼できるデータ ストアに対してクエリを実行するかの決定が明確にされていることですICatalogSearchQuery
。挿入/更新/削除機能を備えた低速で最新のデータが必要な場合は、NHibernate の名前付きクエリ (またはこの場合はリポジトリ) を使用します。また、SQL データベースに変更を加えた場合、アウトプロセスの Worker サービスが最終的に Solr を更新し、結果的に一貫性が保たれることがわかっています。(そして、何かが本当に重要な場合は、イベントをブロードキャストするか、SOLR ストアに直接 ping を実行して、必要に応じてバックグラウンド スレッドで更新するように指示することができます。)
それがあなたにいくつかの洞察を与えることを願っています。