4

product_date_addedフィールドである各製品には、Date追加された日付が含まれていました。また、商品が何回表示されたかを含むフィールドもproduct_viewsあります。int

商品を人気順に表示するために、商品の 1 日あたりのヒット数を計算するアルゴリズムを使用します。

SELECT 
    AVG(product_views / DATEDIFF(NOW(), product_date_added)) as avg_hits
    , product_table.* 
FROM product_table
WHERE product_available = "yes" 
GROUP BY product_id
ORDER BY avg_hits DESC

これは機能しますが、上司は、多くの古い製品が最初に表示されることに気付きました. したがって、彼は基本的に、新しいビューが古いビューよりも重みを持つことを望んでいます。

彼の提案は、1 年以上前のビューはカウントされないというものでした。そのためには、すべてのビューの日付を保持する必要があると思います。これにより、パフォーマンスが低下すると思います。

上司が求めているような人気アルゴリズムを作成する最良の方法は何ですか?

理想的には、テーブル構造を変更しないものを思いつきたいと思っています。それが不可能な場合は、少なくとも既存のデータを使用できるソリューションを考え出して、0 から始めないようにしたいと思います。

4

2 に答える 2

2

(そのように)すべてのビューの日付を保持する必要はありません。代わりに、product_id、day_of_year、countの列を持つテーブルのアイテムごとに最大366行を保持できます。毎日、1年前のすべてのカウントをゼロにするタスクを実行します。非正規化されたデータを気にしない場合、そのタスクはアイテム自体の「カウント」フィールドを更新して高速検索を行うこともできるため、クエリを変更する必要はありません。product_viewsちょうどになりproduct_views_in_the_last_yearます。1日の期間は任意です。人気が正確に1年のウィンドウに基づいていることを気にしないので、バケットの数に応じて、1時間、1週間、または2週間になると思います。対処することをいとわない。

別のスキームは、指数関数的減衰を使用することです。countフィールドを10進型に変換します。1日に1回、各アイテムの数を一定の割合(1%未満、0.1%超)ずつ減らして、ヒットが最近のものであるほど、「重み」が大きくなるようにします。そのため、古い人気が完全になくなることはありませんが、1年前のヒットはあまり貢献しません。ちなみに、このスキームに相当するのは、コードをそのままにして、Webサイト全体が時間の経過とともに指数関数的に人気になるようにすることです;-)

ゼロからの開始を回避することに関しては、1回限りのアクションとして、アイテムの年齢に応じた割合で、各アイテムの数をすぐに減らすことができます。全体として、古いオブジェクトは古いビューを持っていると予想されるため、現在のスキームでは過大評価されています。おそらくいくつかの古いアイテムが最近多くのヒットを獲得しているので、それは絶対確実ではありません。これらのアイテムは、最近のWebサーバーのログを確認するか、1回限りの削減を行う前に1週間または1か月かけてヒットをカウントすることで識別できる場合があります。それをしなくても、彼らの人気の根本的な理由がある場合(彼らが現在あなたのランキングで高く評価されているため、あなたの「最も人気のある」チャートを見ている人々からトラフィックを受け取っているという理由だけでなく)、うまくいけば、彼らは一定の時間で回復するでしょう。

于 2010-09-20T16:48:12.010 に答える
1

このブログ投稿をチェックしてみてください。App Engine を対象としていますが、手法は一般的です。基本的なアプローチは、指数関数的に減衰する人気を持ち、投票/ダウンロードなどを記録するたびに増加することです.

于 2010-09-21T07:18:19.157 に答える