1

コレクション内のすべてのオブジェクトの「人気」フィールドを計算するとします。フィールド「submitTime」とフィールド「votes」の数字までの現在時刻との差に依存します。この操作は 1 時間ごとに実行されます。すべてのオブジェクトに対して関数を実行する最も効率的な方法は何ですか? ほんの一例ですが、それはどんな関数でもかまいません:

function(){
    this.popularity = this.votes / (Date.now() - this.submitTime);
}
4

1 に答える 1

1

すべてのオブジェクトに対して関数を実行し、元のコレクションに人気スコアを保存する場合、すべてのドキュメントを反復処理して新しいスコアを計算して保存するのが最善の方法です。別のコレクションに保存したい場合は、代わりにMapReduceを使用できます。

人気を計算する方法について他のアイデアを受け入れる場合は、さらにオプションがあります:)。

効率の向上

現在のアプローチの効率を改善するには、次のことができます。

  • 更新基準を、投票数が 0 を超えるドキュメントに制限します (そうしないと、とにかくゼロで除算されます)。
  • $set人気度を計算するために必要なフィールドのみを取得し、ドキュメント全体を再保存するのではなく、人気度フィールドを更新します。
  • 個々の投票を追加するときに人気スコアを更新し (1 時間ごとにすべてのスコアを完全に再計算するのを回避)、頻度を減らして (たとえば、毎晩) すべての投票を再計算します。

代替アプローチ

  • 計算ではなく並べ替えによって決定できる人気メトリックを使用します。例: { votes: -1, lastVotedTime: -1, submitTime: -1 }. ただし、これは、古いドキュメントの人気を老朽化させるという要件を満たさない場合があります。

  • イベントやユーザー アクション (記事の公開、ユーザーの閲覧数/投票数など) によってさまざまな人気の値が追加される、数値の人気指標を使用します。時間が経つにつれて、人気は衰退します。DrupalのRadioactivity モジュールは、ルールベースのアプローチでこれを実装します。

MongoDB で後者のアプローチを実装するには、次のことができます。

  • 新しいオブジェクトが特定の値 (例: 1000) から始まる整数popularityフィールドを追加します。
  • さまざまなユーザー アクション (新しい投票、ビューなど) を使用して$inc、適切な量 (たとえば、新しい投票の場合は 50) を使用して人気カウンターを増やします。
  • 定期的にスケジュールされたジョブを使用して、時間の経過とともに人気を低下させます。
  • すべての人気度は正のスコアから始まり、0 以下に減衰するため、更新クエリを人気度が 0 より大きいドキュメントに制限できます。
  • また、人気度スコアを (悪用) 使用して、重要なドキュメントがより長く人気を維持できるようにすることもできます。

「良い人気指標とは何か」については、さらにニュアンスがあり、StackOverflow に関する以前の質問がたくさんあります (例: 「ホットな」質問を判断するには、どの式を使用する必要がありますか? )。

于 2013-04-07T06:47:38.177 に答える