4

Django で最も効率的な方法でかなり複雑なクエリを実行しようとしていますが、開始方法がわかりません。私はこれらのモデルを持っています (これは簡略化されたバージョンです)

class Status(models.Model):
    status = models.CharField(max_length=200)

class User(models.Model):
    name = models.CharField(max_length=200)

class Event(models.Model):
    user = models.ForeignKey(User)

class EventItem(models.Model):
    event = models.ForeignKey(Event)
    rev1 = models.ForeignKey(Status, related_name='rev1', blank=True, null=True)
    rev2 = models.ForeignKey(Status, related_name='rev2', blank=True, null=True)
    active = models.BooleanField()

すべての従属 EventItems が空白rev1でも nulland でもないイベントが最も多い User のリストを生成するクエリを作成したいと考えています。rev2active = True

ユーザーのリストを反復処理し、一致するrev1rev2、およびactive条件についてすべてのイベントをチェックして、それらのイベントを返すことでこれを実行できることはわかっていますが、これはデータベースに負担がかかります。助言がありますか?

ありがとう!

4

3 に答える 3

6

あなたのモデルは壊れていますが、これはあなたがしていたことをよりクリーンな方法で要約する必要があります.

class Status(models.Model):
    status = models.CharField(max_length=200)

class User(models.Model):
    name = models.CharField(max_length=200)
    events = models.ManyToManyField('Event')

class Event(models.Model):
    rev1 = models.ForeignKey(Status, related_name='rev1', blank=True, null=True)
    rev2 = models.ForeignKey(Status, related_name='rev2', blank=True, null=True)
    active = models.BooleanField()

そしてクエリ

User.objects.filter(events__active=True).exclude(Q(events__rev1=None)|Q(events__rev2=None)).annotate(num_events=Count('events')).order_by('-num_events')

これにより、セット内のイベント数でソートされたユーザーのリストが返されます。

詳細については、多対多フィールドを参照してください。

于 2013-02-27T06:29:30.947 に答える
3

すべての従属 EventItem が rev1 で rev2 が空白でも null でもないアクティブ = True であるイベントが最も多いユーザーのリストを生成するクエリを作成したいと考えています。

まず、Event常にこのタイプの を持つオブジェクトが必要ですEventItem

events = Event.objects.filter(active=True)
events = events.exclude(eventitem__rev1__isnull=True)
events = events.exclude(eventitem__rev1='')
events = events.exclude(eventitem__rev2__isnull=True)
events = events.exclude(eventitem__rev2='')

また、 を持たないEventオブジェクトを処理するかどうかを指定しませんでしEventItemた。次の方法でそれらを除外できます。

events = events.exclude(eventitem__isnull=True)

events多くの重複が含まれている可能性があることに注意してください。必要に応じてを投入できevents.distinct()ますが、人間が判読できる必要がある場合にのみ行ってください。

Userそれらを取得したら、必要なオブジェクトを抽出できます。

users = User.objects.filter(event__in=events)

特定のデータベース バックエンド (*ahem* MySQL *ahem*) では、.filter(field__in=QuerySet)パターンが非常に遅いことに気付く場合があることに注意してください。その場合、コードは次のようになります。

users = User.objects.filter(event__in=list(events.values_list('pk', flat=True)))

Event次に、接続されているオブジェクトの数で並べ替えることができます。

from django.db.models import Count
active_users = users.annotate(num_events=Count('event')).order_by('-num_events')
于 2013-02-28T01:48:08.177 に答える
0

次のようなものを試すことができます:

EventItem.objects.exclude(rev1=None).exclude(rev2=None).filter(active=True).values_list('event__user', flat=True)

これにより、ユーザー ID のフラット リストが得られます。ここで、各 ID の頻度は、そのユーザーが持つ EventItem オブジェクトの数です。

を使用してこれをクエリに統合することで、より適切に実行できる可能性がありますが、.annotate()現在の方法はわかりません。

于 2013-02-27T06:41:42.147 に答える