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
默认情况下,所有玩家在他们创建的每个世界中都应该有一个设置。但是由于我们代码中的逻辑错误,有些玩家在某些世界中没有设置。
现在我正试图找到那些 players
在某个世界中没有现有 settings
记录的人,这样我就可以使用播种器为他们创建默认设置。
我试过这样的解决方法:
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
中获取那些 players
而没有现有 settings
记录的方法吗?
使用Ecto.Query.join/5
and 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
上的配置文件。
后者表明您实际上存在设计缺陷。设置和配置文件基本上是同一个实体,表示两次。这就是为什么你有不一致的原因。使用设置中的任何字段丰富配置文件并完全摆脱设置。
我有这些模式:
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
默认情况下,所有玩家在他们创建的每个世界中都应该有一个设置。但是由于我们代码中的逻辑错误,有些玩家在某些世界中没有设置。
现在我正试图找到那些 players
在某个世界中没有现有 settings
记录的人,这样我就可以使用播种器为他们创建默认设置。
我试过这样的解决方法:
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
中获取那些 players
而没有现有 settings
记录的方法吗?
使用Ecto.Query.join/5
and 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
上的配置文件。
后者表明您实际上存在设计缺陷。设置和配置文件基本上是同一个实体,表示两次。这就是为什么你有不一致的原因。使用设置中的任何字段丰富配置文件并完全摆脱设置。