Umgang mit Listentypen mit Esqueleto

144

Ich habe Datentypen definiert als:

data ComitteeView = CommitteeView { committeeId :: CommitteeId
                                  , committeeMembers :: [Person] 
                                  }

data CommitteesView = CommitteesView { committeeView :: [CommitteeView] }

So wie es aussieht, habe ich ein beständiges Modell definiert als:

Person
  name  Text

Committee
  name  Text

CommitteePerson
  personId    PersonId
  committeeId CommitteeId

Ich kann mit Esqueleto ziemlich einfach eine Abfrage erstellen, um eine CommitteeView zu füllen. Es würde ungefähr so ​​aussehen:

getCommitteeView cid = 
  CommitteeView <$> runDB $ 
    select $
      from (person `InnerJoin` pxc `InnerJoin` committee) -> do
        on  (committee ^. CommitteeId ==. pxc ^. CommitteePersonCommitteeId)
        on  (person ^. PersonId       ==. pxc ^. CommitteePersonPersonId)
        where_ (committee ^. CommitteePersonCommitteeId ==. val cid)
        return person

Betrachten Sie nun das Problem der Besiedlung CommitteesView. Im Prinzip erhalten wir genügend Daten zum Auffüllen, indem wir die Unterabfrage in der obigen Abfrage ausführen. Okay, fair genug. Wie kann ich nun "Gruppe nach Haskell-Liste" wie group byin SQL verwenden? Wie kann ich Zeilen falten, um eine Liste mit Personenlisten zu erhalten?

Ich habe den Eindruck, dass esqueletoder Fall als solcher nicht behandelt werden kann (dh es gibt keinen Kombinator, der dies tun würde). Und meine zugrunde liegende Datenbank unterstützt offensichtlich keine Haskell-Listen als Spalte. Aber ich kann sicherlich nicht die einzige Person sein, die sich diesem Problem stellt. Was ist eine effektive Strategie? Eine n-Liste von Listen in eine n-Liste falten? Oder n+1Abfragen ausführen? Gibt es noch andere Möglichkeiten?

keine Männer
quelle
2
Hast du angeschaut Data.List.groupBy?
CDK
@cdk: Ja, damit bin ich gegangen. Es wird jedoch überraschend haarig.
Nomen

Antworten:

2

Esqueleto ist noch NICHT dazu gedacht, die Liste der Unterlisten (mehrdimensionale Liste) sofort zu verarbeiten! Data.List.groupByDas 'cdk', das Ihnen empfohlen wurde, kann nur die Liste selbst gruppieren, aber nicht das, wonach Sie gefragt haben.

Für Ihren Fall würde ich Ihnen eindringlich raten, klassische SQL-Abfragen zu verwenden. Sie können n + 1 Abfragen ausführen, dies jedoch nur, wenn es sich um eine seltene und nicht häufig verwendbare Funktion handelt, die beispielsweise zwischengespeicherte Daten vorbereitet (basierend auf Ihren Variablennamen nehme ich an, dass sie möglicherweise nicht häufig verwendet werden und einen Versuch wert sind). Bei starker Beanspruchung sollten Sie ohne Zweifel die Verwendung von klassischem SQL in Betracht ziehen.

Wenn Sie zu https://github.com/prowdsponsor/esqueleto gehen, finden Sie Folgendes:

Nicht alle SQL-Funktionen sind verfügbar, die meisten können jedoch problemlos hinzugefügt werden (insbesondere Funktionen).

Sie können also versuchen, nach einer neuen Funktion zu fragen. Viel Glück!

Kainax
quelle
Haben Sie einen Link zu einer Quelle dazu? Gerne vergebe ich das Kopfgeld, wenn jemand überprüfen kann, ob dies die richtige Antwort ist, oder wenn Sie eine Dokumentation vorlegen können.
Tech Savant
@ NotoriousPet0 Wenn Sie auf die haskell-Website gehen, finden Sie eine vollständige Liste von Beispielen und Anwendungsfällen, und keiner von ihnen verwendet mehrdimensionale Listen, selbst "inner join". Wenn Sie dort nach einer "Gruppe nach" suchen, werden Sie feststellen, dass sie zum Einschließen mehrerer Spalten in ein Tupel oder zum Sortieren nach zusätzlichen Aggregatfunktionen verwendet werden kann. Dort heißt es auch, dass Entwickler versuchen, Esqueleto so flexibel wie möglich zu gestalten, um jede Abfrage zu unterstützen. Sie können hier also eine zusätzliche Erweiterung anfordern .
Kainax