[英]Ecto/Elixir/Phoenix - Fetch records with no associated record
我有這些模式:
schema "players" do
field :email, :string
has_many :profiles, MyApp.Profile
has_many :worlds, through: [:profiles, :world]
end
schema "worlds" do
field :name, :string
has_many :profiles, MyApp.Profile
has_many :players, through: [:profiles, :player]
end
schema "settings" do
field :mode, :string
belongs_to :player, MyApp.Player
belongs_to :world, MyApp.World
end
默認情況下,所有玩家都應該在他們創建的每個世界中都有一個設置。 但是由於我們的代碼中的邏輯錯誤,一些玩家在某些世界中沒有設置。
現在我試圖找到那些在某些世界中沒有現有settings
記錄的players
,這樣我就可以使用播種機為他們創建默認設置。
我試過這樣的解決方法:
query = from profile in Profile
query
|> Repo.all()
|> Enum.each(fn profile ->
case get_settings(profile.player_id, profile.world_id) do
nil ->
create_settings(profile.player_id, profile.world_id)
_ ->
:ok
end
end)
它有效,但我想避免使用 case 語句。 它花費了大量的數據庫工作。 有沒有辦法在某些worlds
中使用查詢來獲取那些沒有現有settings
記錄的players
?
或多或少地使用Ecto.Query.join/5
和Ecto.Query.subquery/2
subquery =
from profile in Profile,
join: player in Player,
on: player.id == profile.player_id,
join: world in World,
on: world.id == profile.world_id
query =
from setting in Settings,
join: profile in subquery(subquery),
on: setting.player_id == profile.player_id and
setting.world_id == profile.world_id
或者,更簡單的是,您可以直接將設置加入到player_id
和world_id
的配置文件中。
后者表明您實際上存在設計缺陷。 設置和配置文件基本上是相同的實體,代表兩次。 這就是為什么你有不一致的地方。 使用設置中的任何字段豐富配置文件並完全擺脫設置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.