3

こんにちはstackoverflowの皆さん、

成長し続けるRailsプロジェクトがあり、ニーズに合わせてスフィンクスを適切に利用する方法がわからないため、検索で最初のパフォーマンスの問題が発生します。「JavaPHPソフトウェア開発者」のような検索クエリがあります。私たちの問題は、ランキングが複数のもので機能するはずだということです。

検索フィールドとして、タグリスト、説明、タイトルがあります。用語の1つがフィールドの1つに含まれている場合、たとえば2ポイントを取得する必要があります。より多くのフィールドにある場合はより多くのポイントがありますが、同じフィールドに複数回ある場合は複数のポイントはありません。次の問題は、同義語を含む大きなファイルがあり、これもチェックする必要があることです。次のようになります。

Java > Java
Java-EE > Java
...

したがって、Java-EEが見つかった場合、それもいくつかのポイントを獲得するはずですが、同義語であるためのペナルティがあります。

ポイントの最大数は、表示される5つ星のように5になります。スフィンクスでは適切にランク付けできないため、現時点ではプレーンルビーで実行されて遅くなるため、迅速な解決策があれば便利です。

別の検索エンジンを使用した解決策がある場合は、変更される可能性があるため、これも非常に便利です。

よろしくお願いします。質問をクリアするためのすべてのスペル修正と質問は大歓迎です。

4

2 に答える 2

2

パフォーマンスの問題のほとんどは、sphinx の使用方法を変更することで解決できます。まず、sphinx でデータをインデックス化する方法に対処する必要があります。インデックス作成中に何らかの処理を行うと、検索が速くなり、結果の関連性が高まります。次に、検索用語に取り組み、最後に、使用するランキング アルゴリズムを決定します。

例として「タイトル」フィールドを使用しますが、ロジックはすべてのフィールドに複製できます。

索引付け

sphinx に 2 つのフィールド ("title" と "title_synonyms") を追加します。データベース内の各レコードに対して、次の操作を行います:-

  • 単語に対して DISTINCT を実行して重複を削除します ("Ruby Developer / Java Developer" は "Ruby Developer / Java" になります。これにより、レコードが検索時に重複に対して 2 つのスコアを取得することがなくなります。これは "title" に入ります。

  • 上記の DISTINCT タイトルを取得し、すべての単語を拡張同義語に置き換えます。拡張を容易にするために、シノニムを DB に入れることをお勧めします。テキストは「Ruby Developer / Java-EE」になります。各単語をすべての同義語に置き換える必要があります。Java に 2 つのシノニムがある場合、両方ともフィールドにある必要があります。これは「title_synonyms」に入ります

検索中

sphinx には 2 つのフィールドがあるため、それぞれに異なる重みを付けることができます。"title" は "10" の重みを、"title_synonyms" は "3" の重みを得ることができます。つまり、レコードが元のタイトルの 1 つより上位にランク付けされるには、4 つの同義語に一致する必要があります。ニーズに合わせてウェイトをいじることができます。

ユーザーが「Java Developer」を検索していたとします。検索フレーズについては、次の操作を行います:-

  • 重複する単語を削除する
  • 検索フレーズの各単語の類義語を取得する
  • Sphinx のマッチング モードを SPH_MATCH_EXTENDED に設定する

上記のルールは、sphinx での検索が次のようになることを意味します:-

@title "Java 開発者" | @title_synonyms "Java-EE"

完全一致を語彙素より上位にランク付けしたい場合、検索クエリは次のようになります。

@title ("Java 開発者" | "=Java = 開発者") | @title_synonyms ("Java-EE" | "=Java-EE")

ただし、これを適切に機能させるには、SPH_RANK_PROXIMITY_BM25 または SPH_RANK_SPH04 を使用する必要があります。

ランキング

組み込みのランキング アルゴリズムのいずれかを試して、結果がどのように見えるかを確認できます。最初に SPH_RANK_MATCHANY または SPH_RANK_WORDCOUNT をお勧めします。

近接および完全一致ランキングには、独自のアルゴリズムを使用できる SPH_RANK_PROXIMITY_BM25、SPH_RANK_SPH04、または SPH_RANK_EXPR を使用します。

結論

これで、高速かつ正確な検索ができるはずです。Ruby アプリケーションで実行する必要がある作業はほとんどなく、ほとんどの作業は sphinx 内 (あるべき場所) で行われます。

お役に立てれば...

于 2012-04-15T08:13:35.523 に答える
1

このパフォーマンスの問題は、アルゴリズムの問​​題です。

sphinx やデータベース エンジンなどのバックエンド ツールを利用する方法で問題を表現できない場合は、Ruby で処理を行っていることになり、パフォーマンスの問題が発生しやすくなります。

まず、sphinx (またはその他の検索エンジン) とデータベースでできる限りのことを行います。データベースは過去半世紀にわたって高度に最適化されてきたため、Ruby に取り込まれるデータを事前に消化すればするほど、Ruby コードで行う必要が少なくなり、高速になる可能性があります。

たとえば、キーワードに対して sphinx を実行します。シノニムに対しても sphinx を実行します。すべての回答を上位の結果に限定し、結果をマージします。そうすれば、エントリのデータベース全体を考慮しなくても、Ruby コードは高い結果が得られる可能性が高いものに限定されます。

Ruby では、最も重要なことは高次アルゴリズムを避けることです。つまり、低次アルゴリズムを使用していることを確認してください。

生データを処理するときに、上位の結果を配列に保持し、配列をソートまたはスキャンしようとすると、N 乗の順序になります。つまり、順序は、生のエントリの数と配列に保持する要素の数の積になります。

問題に最適なアルゴリズムは、コンテナーのようなヒープまたは b ツリーによって実装される優先キューです。どちらも N-log-N オーダー (N のログの N 倍)、またはコンテナーに保持するアイテム数のログに生データ レコードの数を掛けたものです。

ヒープはバイナリ ツリーであり、ツリー内の各ノード (リーフだけでなく各ノード) に評価されたレコードがあります。各レコードの下のノードは、すべてランクが低くなります。これをヒープ状態と呼びます。

ヒープ状態を維持するために、要素を追加したり、上位の要素を取り出したり、最下位の要素を置き換えたりするアルゴリズムがあります。ウィキペディアでバイナリ ヒープを検索します。

あなたのサイトが上位 100 位の結果を表示するとします。ルートが最下位のヘルプを維持します。処理している最初の 100 個の未加工レコードを追加して、ヒープを設定します。

ここで、レコード 101 以降について、そのランクをルートと比較します。新しいレコードのランクが高い場合は、削除アルゴリズムを使用してヒープを 99 ノードに減らし (これにより、ヒープ内の最低ランクのレコードが削除されます)、新しいレコードをヒープに追加します。

すべての記録を確認すると、上位 100 位の結果が表示されます。ヒープ削除アルゴリズムは、それらを逆の順序で引き出します。

于 2012-04-14T14:40:54.830 に答える