簡體   English   中英

Ecto/Elixir/Phoenix - 獲取沒有關聯記錄的記錄

[英]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/5Ecto.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_idworld_id的配置文件中。

后者表明您實際上存在設計缺陷。 設置和配置文件基本上是相同的實體,代表兩次。 這就是為什么你有不一致的地方。 使用設置中的任何字段豐富配置文件並完全擺脫設置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM