2017-02-20 4 views
0

Sagen, ich habe folgende Ecto-Modelle: mitWie wird eine Zuordnung für jeden Datensatz vorab geladen?

  • ForumCategory, has_many :forums
  • Forum, belongs_to :forum_category, has_many :forum_topics
  • ForumTopic, belongs_to :forum

Say dann laden Ich möchte alle Einträge von ForumCategory Alle ihre zugeordneten Forum Einträge vorinstalliert und die neuesten.210 für jede dieser:

ForumCategory ->Forum ->ForumTopic

Die Vorbelastung Foren Forum Kategorien ist trivial:

ForumCategory 
|> preload(:forums) 

nun auch vorzuladen wir die neuesten Forumsthema wollen, aber wir Ich möchte nur das jeweils neueste Thema für jedes Forum laden. Daher laden wir nicht die gesamte Liste der Forenthemen aus der Datenbank ein (es wird viele geben).

Das scheint auf den ersten Blick zu funktionieren, aber es wird schnell klar, dass diese Abfrage immer nur ein Forumthema zurückgibt, nicht ein Forum, sondern ein einziges Forenthema insgesamt, was sich auch aus der eigentlichen SQL-Abfrage ergibt ausgeführt wird:

SELECT f0."id", f0."title", f0."body", f0."pinned", f0."forum_replies_count", f0."deleted_at", f0."inserted_at", f0."updated_at", f0."forum_id", f0."user_id", f0."forum_id" 
FROM "forum_topics" AS f0 WHERE (f0."forum_id" = ANY($1)) 
ORDER BY f0."forum_id", f0."inserted_at" DESC 
LIMIT 1 

meine Frage also ist, wie kann ich machen Ecto Vorbelastung nicht nur ein einzelner Datensatz insgesamt aber eine pro-Forum, das auf jedem Forum Kategorie vorbelastet?

Antwort

0

endete ich mit dieser Lösung, die eine Kombination von Joins und Fensterfunktionen verwendet:

defmodule MyApp.ForumTopic do 
    def latest_over_forum(per \\ 1) do 
    from outer in __MODULE__, 
     join: inner in fragment(""" 
     SELECT *, row_number() OVER (
      PARTITION BY forum_id 
      ORDER BY inserted_at DESC 
     ) FROM forum_topics 
     """), 
     where: inner.row_number <= ^per and inner.id == outer.id 
    end 
end 

forum_topics_query = ForumTopic |> ForumTopic.latest_over_forum 
ForumCategory 
|> preload([forums: [forum_topics: ^forum_topics_query]]) 
|> Repo.all 
Verwandte Themen