4

ここでの私の目標は、reddit のフロント ページと同様のシステムを生成することです。

私には物事があり、簡単にするために、これらの物事には投票があります。私が生成した最高のシステムは、時間減衰を使用することです。半減期が 7 日間の場合、今日の投票が 20 ポイントの価値がある場合、7 日後には 10 ポイントの価値があり、14 日後には 5 ポイントの価値になります。

問題は、これは私が非常に満足している結果を生み出しますが、スケールしないことです. 投票ごとに、他のすべての投票の値を効果的に再計算する必要があります。

だから、私は考えを逆転させることができるかもしれないと思った。今日の投票は 1 ポイントの価値があります。今から 7 日後の投票は 2 ポイントの価値があり、今から 14 日後の投票は 4 ポイントの価値があります。投票ごとに 1 つの行を更新するだけでよいため、これはうまく機能します。問題は、年末までに、とてつもなく膨大な数を保持できるデータ型が必要になることです。

というわけで、ひどいランキングになった線形成長を使ってみました。多項式の成長 (サイトの立ち上げと提出からの日数の 2 乗と 3 乗) を試したところ、わずかに良い結果が得られました。ただし、わずかに良い結果が得られると、すぐに維持不可能な数値に再び近づきます。

だから、私はあなたのスタックオーバーフローに来ます。天才的なアイデアを持っている人、またはこのシステムをモデル化する方法に関するアイデアへのリンクを持っている人は、Web アプリケーションに合わせて適切に拡張できます。

4

4 に答える 4

2

私もこれをやろうとしてきました。解決策らしきものを見つけたのですが、残念ながら計算の仕方を忘れてしまい、理解に苦しみます。

アイデアは、スコアのログを保存し、それによってソートすることです。これにより、数値がオーバーフローしなくなります。

このドキュメントでは、数学について説明します。 https://docs.google.com/View?id=dg7jwgdn_8cd9bprdr

そして、私が見つけたコメントはここにあります: http://blog.notdot.net/2009/12/Most-popular-metrics-in-App-Engine#comment-25910828

于 2012-01-08T20:39:03.760 に答える
0

ここでは遅いので、誰かが私の数学をチェックできることを願っています. これは指数関数的減衰に等しいと思います。

MySQL の BIGINT の最大値は 2^64 です

簡単にするために、時間間隔として 1 日を使用します。サイトが開設されてからの日数を n とします。

  1. 整数変数を作成します。それを X と呼び、0 から始めましょう
  2. 加算操作によってスコアが 2^64 を超える場合は、最初にすべてのスコアを 2^n で割って更新し、次に X を n に設定します。
  3. 投票ごとに、スコアに 2^(nX) を追加します。

したがって、精神的には、底 10 を使用するほうが理にかなっています。合計すると、数がどんどん長くなります。スコアをインクリメントする値には多くの桁があるため、下位桁の数字は気にしません。これは、下位の桁が非常にカウントを停止することを意味します。したがって、それらがカウントされない場合は、小数位を気にするポイントまでスライドさせて、小数点以下の桁をある時点で切り捨ててみませんか。これを行うには、毎回加算する金額の小数点以下をスライドさせる必要があります。

これには何か問題があるように感じずにはいられません。

于 2012-01-06T07:36:29.197 に答える
0

使用できる疑似クエリを 2 つ示します。スケーラビリティに実際には対応していないことは知っていますが、メソッドを提供していると思います。

SELECT article.title AS title, SUM(vp.point) AS points
FROM article
LEFT JOIN (SELECT 1 / DATEDIFF(NOW(), vote.created_at) as point, article_id
  FROM vote GROUP BY article_id) AS vp  
ON vp.article_id = article.id

または(結合ではなく、少し速くなると思いますが、水分補給が難しくなります)、

SELECT SUM(1 / DATEDIFF(NOW(), created_at)) AS points, article_id
FROM vote
WHERE article_id IN (...) GROUP BY article_id

これらのクエリの利点は、いつでも同じデータを使用して実行でき、常に同じ回答が返されることです。それらはデータを破壊しません。

必要に応じて、クエリをバックグラウンド ジョブで実行することもできますが、それでも同じ結果が得られます。

于 2012-01-06T17:27:50.530 に答える
0

さて、投票ごとにそれを行うための1つの解決策を考えました。問題は、投票を保存するために、両側にアトミックな pop/push を持つリンクされたリストが必要なことです (たとえば、Redis リストですが、おそらく RAM には入れたくないでしょう)。

また、減衰間隔が一定 (例: 1 時間) であることも必要です。

こんなふうになります:

  1. 投票ごとにスコアを更新し、この投票の次の減衰時間をリストの末尾にプッシュします
  2. 次に、リストの先頭から最初の投票をポップします
  3. 腐るほど古くない場合は、頭に押し戻します
  4. それ以外の場合は、合計スコアから必要な金額を差し引き、更新された情報を末尾にプッシュします
  5. 十分な数の投票が得られるまで、ステップ 2 から繰り返します (ステップ 3)。

もちろん、バックグラウンドでヘッドをチェックして、誰も投票していない投稿をクリアする必要があります.

于 2012-01-06T07:16:49.197 に答える