web-dev-qa-db-ja.com

djangoクエリで同じフィールド値をカウントする最も効率的な方法

たくさんのフィールドを持つモデルがあるとしましょう。しかし、気になるのはcharfieldだけです。 charfieldは何でもかまいませんので、可能な値はわかりませんが、値が頻繁に重複していることがわかります。つまり、「abc」のオブジェクトを20個、「xyz」のオブジェクトを10個、または「def」のオブジェクトを50個、「stu」のオブジェクトを80個、オーバーラップのない40000個のオブジェクトを作成します。

オブジェクトを効率的にカウントするにはどうすればよいですか?私が返したいのは次のようなものです:

{'abc':20、 'xyz':10、 'other':10,000}

またはそのようなもので、大量のSQL呼び出しをしません。

編集:

ちょっと最近編集しているので誰かに見られるかわかりませんが...

私はこのモデルを持っています:

 class Action(models.Model):
 author = models.CharField(max_length = 255)
 purl = models.CharField(max_length = 255、null = True)

そして答えから、私はこれをしました:

 groups = Action.objects.filter(author = 'James')。values( 'purl')。annotate(count = Count( 'purl'))

だが...

これがグループとは次のとおりです。

 {"purl": "waka"}、{"purl": "waka"}、{"purl": "waka"}、{"purl": "waka"}、{"purl": "mora"}、{"purl": "mora"}、{"purl": "mora"}、{"purl": "mora"}、{"purl": "mora"}、{"purl": "lora"} 

(私はちょうどダミーをダミー値で満たしました)

私が欲しいのは

 {'waka':4、 'mora':5、 'lora':1} 

うまくいけば、誰かがこの編集を見るでしょう...

編集2:

どうやらmy database(BigTable)does not support the aggregate functions of Djangoそしてこれが私がすべての問題を抱えている理由です。

48
DantheMan

「count ... group by」のようなものが必要です。これは、DjangoのORMの集約機能を使用して行うことができます。

from Django.db.models import Count

fieldname = 'myCharField'
MyModel.objects.values(fieldname)
    .order_by(fieldname)
    .annotate(the_count=Count(fieldname))

この問題に関する以前の質問:

77
beerbajay

これは集約と呼ばれ、Django 直接サポート です。

カウントしたい値をフィルタリングし、値のリストを取得し、それらをカウントすることにより、1組のデータベース呼び出しで正確な出力を得ることができます。

from Django.db.models import Count
MyModel.objects.filter(myfield__in=('abc', 'xyz')).\
        values('myfield').annotate(Count('myfield'))
16
Daniel Roseman

クエリセットでDjangoのCountaggregation を使用してこれを実現できます。このようなもの:

from Django.db.models import Count
queryset = MyModel.objects.all().annotate(count = Count('my_charfield'))
for each in queryset:
    print "%s: %s" % (each.my_charfield, each.count)
7
Manoj Govindan

フィールド値が常に特定のケースであることが保証されていない限り、カウントを実行する前にフィールド値を変換すると便利です。つまり、「Apple」と「Apple」は同じものとして扱われます。

from Django.db.models import Count
from Django.db.models.functions import Lower

MyModel.objects.annotate(lower_title=Lower('title')).values('lower_title').annotate(num=Count('lower_title')).order_by('num')
1
alstr