1

Meteor.js を使用してフィルター処理されたライブ検索モジュールに取り組んでいます。

ユースケースと問題:

ユーザーは、すべてのユーザーを検索して友達を見つけたいと考えています。しかし、各ユーザーが完全なユーザー コレクションを要求する余裕はありません。ユーザーは、チェックボックスを使用して検索をフィルタリングします。一致したユーザーを購読したいです。それを行う最良の方法は何ですか?

クライアント側でクエリを作成し、それをメソッドに送信して、目的のユーザーのセットを取得する方がよいと思います。しかし、フィルタリング基準が変更された場合、新しいサブスクリプションは古いサブスクリプションをすべて消去するのでしょうか? なぜなら、 me を返す最初の検索を行い[usr1, usr3, usr5]、その後me を返す検索を行う場合[usr2, usr4]、最初のセットを保持し、新しいセットをクライアント側の購読済みコレクションに単純に追加するのが最善だからです。

さらに、[usr1、usr3、usr2、usr4] を返す必要がある 3 番目の調査を行った場合、自動実行されたサブスクリプションは、結果セット全体を既にコレクションに持っているため、何も送信しません。

目標は、サーバーからの処理とデータ転送を節約することです。

私にはいくつかのアイデアがありますが、簡単に包括的​​に共有できるほど十分にコーディングしていません。

時間とパフォーマンスの節約の観点から、可能な限り関連性を高めるために、どのようにアドバイスしていただけますか?

ありがとうございます。

デビッド

4

2 に答える 2

1

アプリケーションによって異なりますが、おそらく空でない文字列をパブリッシャーに送信し、パブリッシャーはその文字列を使用してユーザー コレクションで一致する名前を検索します。例えば:

Meteor.publish('usersByName', function(search) {
  check(search, String);

  // make sure the user is logged in and that search is sufficiently long
  if (!(this.userId && search.length > 2))
    return [];

  // search by case insensitive regular expression
  var selector = {username: new RegExp(search, 'i')};

  // only publish the necessary fields
  var options = {fields: {username: 1}};

  return Meteor.users.find(selector, options);
});

フィールドを制限する理由については、よくある間違いも参照してください。

パフォーマンス

Meteor は、各クライアントが各パブリッシャーに対して持っている現在のドキュメント セットを追跡するのに十分賢いです。パブリッシャーが再実行すると、セット間の差分のみを送信することがわかっています。したがって、上記の状況はすでに対処されています。

  1. ユーザーを購読していた場合: 1,2,3
  2. 次に、ユーザー 2、3、4 のサブスクリプションを再開しました
  3. サーバーはremoved1 のメッセージを送信し、4 の追加メッセージを送信します。

再実行する前にサブスクリプションを停止した場合、これは発生しないことに注意してください。


removed私の知る限り、単一のサブスクリプションのパラメーターを変更するときにメッセージを回避する方法はありません。2 つの可能な (しかしトリッキーな) 代替案を考えることができます。

  1. 以前のすべての検索クエリの共通部分を蓄積し、購読時にそれを使用します。たとえば、ユーザーが を検索して{height: 5}から を検索した場合、{eyes: 'blue'}で購読できます{height: 5, eyes: 'blue'}。これをクライアントに実装するのは難しいかもしれませんが、最小限のネットワーク トラフィックで目的を達成できるはずです。

  2. アクティブなサブスクリプションを蓄積します。ユーザーが検索を変更するたびに既存のサブスクリプションを変更するのではなく、新しいドキュメント セットの新しいサブスクリプションを開始し、サブスクリプション ハンドルを配列にプッシュします。テンプレートが破棄されたら、すべてのハンドルを反復処理して呼び出す必要がありstop()ます。これは機能するはずですが、より多くのリソース (ネットワークとサーバーのメモリ + CPU の両方) を消費します。

これらのソリューションのいずれかを試す前に、それらを使用せずに最悪のシナリオをベンチマークすることをお勧めします。私の主な懸念は、かなり厳格な管理を行わないと、連続した検索の後にユーザー コレクション全体を公開してしまう可能性があることです。

于 2015-05-29T21:51:19.637 に答える
0

サーバーを簡単に使いたい場合は、クライアントに送信するデータをできるだけ少なくする必要があります。つまり、友達ではないクライアントに送信するドキュメントはすべて無駄です。ですから、その無駄をすべて排除しましょう。

フィルタを収集します (例: filters = {sex: 'Male', state: 'Oregon'})。次に、フィルターに基づいて検索するメソッドを呼び出します (例: Users.find(filters)。さらに、独自の独自のランキング アルゴリズムを実行して、その人が友人である可能性を % で判断できます。おそらく、IP アドレスからの距離 (または電話の GPS 履歴から) に基づいて決定します)。 )、相互の友人など. これは、効率の面で少し利益をもたらします. GPS 座標やその他の非常にユニークな属性などのインデックスを作成します. 複合インデックスを試してみてください. ただし、インデックスが増えると書き込みが遅くなることを覚えておいてください.

これで、可能性が最も高いものから最も可能性が低いものへとランク付けされた、すべての可能な友人のカーソルができました。

次に、サブスクリプションをそれらの友達に合わせて変更しますが、limit:20そこに入れます。また、必要なフィールドのみを送信してください。そうすれば、ユーザーがこのステップをスキップしたい場合でも、20 個の部分的なドキュメントをネットワーク経由で送信するだけで済みます。次に、ユーザーがクリックできる無限スクロールまたは「もっと読み込む」ボタンを用意します。さらにロードすると、追加のサブスクリプションになるため、重複した情報が再送信されることはありません。Discover Meteor はこのパターンを非常に詳細に説明しているので、ここでは省略します。

数回クリック/スクロールした後、ユーザーはそれ以上友達を見つけられないため (あなたが賢くて並べ替えたため)、友達は試行をやめて次のステップに進みます。200 人の友だち候補を返し、60 人を超えると試行をやめた場合、140 のドキュメントがパイプラインを通過するのを防いだことになります。あなたの効率があります。

于 2015-05-29T21:16:24.033 に答える