0

ユーザーが自分のサイトに投稿した回数を数えて、サイトでランク付けできるようにしたいと考えています。まさにそれを行う美しいコードを書くことができましたが、それはユーザーごとに行われました。

ユーザーはフィールドごとに異なる量のポイントを取得するため、モデルの特定のフィールドと、ユーザーがそれらに値を入力したかどうかをチェックします。次に、これらの値に重みを掛けて合計スコアを求めます。

少しのコードよりも優れているものはありません。

class UserContribCounter(object):
    """Can count the number of points a user got for his contributions"""
    weight_dict = {'poster':2, 'title':1}

    def __init__(self, user):
        if isinstance(user, User):
            self.user = user
        else:
            raise Exception('Not a valid user instance.')

    def set_contrib_points(self):
        """Some dark magic counts the number of times a certain field was filled out"""
        self.unweighted = Movie.objects.filter(user = self.user).aggregate(poster=Count('poster'),title=Count('title'))

    def get_contrib_points(self):
        """Multiplies the number of times a field was filled out with their weights to calculate the total number of points"""
        try:
            self.unweighted
        except AttributeError:
            self.set_contrib_points()

        return sum([self.weight_dict[key] * value for key, value in self.unweighted.items()])

トップ 10 も表示したいので、トップ 10 のユーザーを取得する必要があります。これは、現時点では失敗し続けている複雑な集計を作成する必要があるか、次の方法でシグナルを使用できることを意味します。

モデルが保存されたら、post_save シグナルをキャッチします。次に、既存のクラスを使用してユーザーのポイントを再計算し、ユーザー プロファイルに保存します。このようにして、プロファイルの値でユーザーを並べ替えることができますが、これは簡単なことです。

問題は、モデルが保存されるたびに再カウントを行うこと、またはかなり複雑な集計関数を行うことのどちらがより効率的かということです。これは多くのことに依存することはわかっていますが、概念的な観点からは、どちらかを選択する理由があるはずです。集約でチェックするフィールドの一部はリレーショナルでもあることに注意してください。そのため、パフォーマンスにどのように影響するかはわかりません.

前もって感謝します、

tBuLi

4

1 に答える 1

0

これは、モデルが変更される頻度と、トップ 10 がどれだけ正確で最新である必要があるかによって異なります。それだけの価値があるため、トップ 10 を 1 時間または 1 日キャッシュすることもできます。一方、django の集計ではカバーされない複雑な順序付けや処理を行う必要がある場合は、非正規化の恩恵を受けることができます。

そして最終的には、現実世界での使用におけるボトルネックを実際に発見することになります。できる限り小さなことから、真剣に取り組みます。

于 2012-08-20T05:15:11.457 に答える