Ich versuche, ein Modell in Django 1.9 zu bauen, die ein Schlüssel, Wert-Paar (Wörterbuch) hat Ermöglicht die Aggregation von Abfragegruppen (min, mix, usw.). Ich habe versucht, die JSONField zu verwenden:Wie ein Dictionary-Feld in einem Django-Modell zu haben und Aggregation (min/max) auf diesem Feld über Dictionary Keys
#models.py
from django.contrib.postgres import fields as pgfields
class Entry(models.Model):
pass
class Scorer(models.Model):
name = models.CharField(max_length=100)
class EntryScoreSet(models.Model):
scorer = models.ForeignKey(Scorer)
entry = models.ForeignKey(Entry, related_name="scorecard")
scores = pgfields.JSONField(default={})
....
# shell test
import random
entry = Entry()
scorer,_ = Scorer.objects.get_or_create(name="scorer1")
entry.save()
for i in range(0,10):
scores = dict(scoreA=random.random(),
scoreB=random.random(),
scoreC=random.random(),
)
entry_score_set=EntryScoreSet(scores=scores, entry=entry, scorer=scorer)
entry_score_set.save()
entry.scorecard.filter(scorer="scorer1").aggregate(Max("scores__scoreA"))
Aber ich laufe in die Fehler von this ticket (im Grunde wird die Aggregation wird nicht unterstützt).
Eine zweite Option ist ein Schlüssel, Wert-Paar-Modell (ähnlich this answer) zu verwenden:
class Score(models.Model):
entry_score_set = models.ForeignKey(EntryScoreSet, db_index=True,
related_name="scores")
key = models.CharField(max_length=64, db_index=True)
value = models.FloatField(db_index=True)
Aber ich weiß nicht, wie man eine Aggregation über eine Abfragesatz für einen bestimmten ein Schlüssel bekommen würde Wert.
Wie würde ich ein Schlüssel/Wert-Paar-Feld in Django implementieren, das die Aggregation einer Abfrage für den Wert eines bestimmten Schlüssels ermöglicht?
EDIT:
Hier ist ein Ausschnitt, das zeigt, was ich mit Pandas tun will und die zweite Option (Schlüssel, Paar-Modell):
import django_pandas.io as djpdio
scds=Scorecard.objects.filter(
entry__in=Entry.objects.order_by('?')[:10],
scorer__name="scorer1")
scorecard_base=djpdio.read_frame(scds,fieldnames=["id","entry__id","scorer__name","scores__id"])
scores=djpdio.read_frame(Score.objects.filter(scorecard__in=scds),fieldnames=["id","key","value"])
scorecard_=(scorecard_base
.merge(scores,left_on="scores__id",right_on="id")
.pivot_table(index="entry__id",columns="key",values="value").reset_index())
scorecard=scorecard_base.merge(scorecard_,on="entry__id")
scorecard["scoreA"].max()
Ist so etwas möglich Djangos mit ORM? Wie wäre die Effizienz mit der Verwendung der Pandas Pivot-Funktion vergleichbar?
Hat die 'EntryScoreSet' Laden etwas anderes, dass Noten:
Diese Sie eine Ausgabe wie so geben werden? Wenn nicht, könnten Sie einfach ein "Score" -Modell mit einem Fremdschlüssel direkt an "Entry" senden, und dann ist die Aggregation einfach (gerne ein Beispiel zu veröffentlichen, sobald Sie geklärt haben, ob das Zwischenmodell erforderlich ist). – solarissmoke
Es hat einen zusätzlichen Fremdschlüssel, Einträge haben Punkte von mehreren Scorern. Ich werde aktualisieren. – jmerkow
Wäre es möglich, die Schlüssel, Wert-Paare in zwei Arrays zu trennen und diese Operation durchzuführen? ein ArrayField (CharField), ArrayField (FloatField). Vielleicht verwenden Sie einen F() Ausdruck, um den Index von 'scoreA' zu erhalten – jmerkow