0

MyISAMを使用してMySQLで実行されているDjangoで、クエリセットのCountアノテーションが誤った結果を返します。SQLステートメントを確認しましたが、MySQLに問題があるのか​​、Djangoコードに問題があるのか​​わかりません。

Djangoモデル:

class Resource(models.Model):
    ...
    voters = models.ManyToManyField(User, related_name="resources")

コード:

resources = Resource.objects.filter(
    ...
).annotate(
    votes=models.Count('voters')
).order_by('-votes')
print resources.query

印刷されたSQL:

SELECT
...,
COUNT(`app_resource_voters`.`user_id`) AS `votes`
FROM `app_resource`
...
LEFT OUTER JOIN `app_resource_voters`
ON `app_resource`.`id` = `app_resource_voters`.`resource_id`
...

phpMyAdminでクエリをテストすると、投票に対して間違った値が返されます。実際には、投票者の数に、リソースに存在する他の属性への外部キーの関連付けの数を掛けたものが返されます(非常に混乱します)。DjangoとSQLは正しく見えますか?これは、MySQLの問題であることを意味しますか?MyISAM以外のものに交換するか、PostgreSQLに交換することをお勧めしますか?

4

1 に答える 1

0

回避策として使用できる可能性が他に 2 つあります。

1 つ目は単純ですが、効率は低くなりますResource。モデルにメソッドまたはプロパティを作成します。

class Resource(models.Model):
    ...

    @property    # or @django.utils.functional.cached_property
    def votes(self):
        return self.voters.count()

2番目は使用することextra()です:

resources = Resource.objects.filter(
    ...
).extra(
    select={
        'votes': 'SELECT COUNT(*) FROM app_resource_voters WHERE app_resource.id = app_resource_voters.resource_id'
    },
).order_by('-votes')
于 2012-06-09T11:34:54.817 に答える