2017-10-06 11 views
0

私のプロジェクトのうちの1つに対して複雑な(私にとっては)クエリを構築しようとしています。 Djangoのバージョンは1.11.4、PostgreSQLのバージョンは9.6です。Django 1.11.4 PostgreSQL SELECT ARRAY to django orm

ここにモデルです。

class Event(models.Model): 
    ... 
    name = models.CharField(max_length=256) 
    classification = models.ForeignKey("events.Classification", related_name="events", null=True, blank=True) 
    ... 

class Classification(models.Model): 
    ... 
    segment = models.ForeignKey("events.ClassificationSegment", related_name="classifications", blank=True, null=True) 
    ... 

class ClassificationSegment(models.Model): 
    ... 
    name = models.CharField(max_length=256) 
    ... 

ここでブロックされています。先に進むことはできません。

from django.db.models import CharField, Value as V 
from django.db.models.functions import Concat 
from django.contrib.postgres.aggregates import ArrayAgg 
from django.db.models import OuterRef, Subquery 
import events.models 


event_subquery = events.models.Event.objects.filter(classification__segment=OuterRef('pk')) \ 
.annotate(event=Concat(V('{id:'), 'id', V(', name:"'), 'name', V('"}'), output_field=CharField())) 

final_list = events.models.ClassificationSegment.objects.annotate(
event_list=ArrayAgg(Subquery(event_subquery.values('event')[:6]))) 

私は生のクエリを持っています。ここにあります。

final_events = events.models.ClassificationSegment.objects.raw('SELECT "events_classificationsegment"."id", "events_classificationsegment"."name", (SELECT ARRAY(SELECT CONCAT(\'{id:\', CONCAT(U0."id", CONCAT(\',\', \'name:"\', U0."name", \'"}\'))) AS "event" FROM "events_event" U0 INNER JOIN "events_classification" U1 ON (U0."classification_id" = U1."id") WHERE U1."segment_id" = ("events_classificationsegment"."id") LIMIT 6)) AS "event_list" FROM "events_classificationsegment"') 

結果はスクリーンショットで確認できます。私は正しい方法でいると思う。誰でも助けてくれますか?

enter image description here

感謝。

答えて

2

Postgresがサブクエリからの配列を作るのは本当に良い方法があります。

SELECT foo.id, ARRAY(SELECT bar FROM baz WHERE foo_id = foo.id) AS bars 
    FROM foo 

ORM内これを行うには、Subqueryのサブクラスを定義することができます

class Array(Subquery): 
    template = 'ARRAY(%(subquery)s)' 

をし、これを使用しますあなたのクエリーセットで:

queryset = ClassificationSegment.objects.annotate(
    event_list=Array(event_subquery.values('event')[:6]) 
)