使用具有 has_many 关系的结构播种数据库时找不到列
Column not found when seeding database with structs with has_many relationship
我首先尝试用一个简单的一层深度结构为我的数据库播种,效果很好。但是,当我添加一个路径映射以匹配我的顶级结构路径字段时,我得到了错误。
** (Postgrex.Error) ERROR 42703 (undefined_column): column "apis_id" of relation "paths" does not exist
我已经尝试删除 apis_id 但我相信我需要该字段来预加载我的 ApiController 中的 Path 结构。也许问题出在我的 has_many
/belongs_to
语法上,尽管我相信我的语法是正确的,并且我已经尝试淹没其他 foreign_keys 和引用但没有运气。
我也可能只是遗漏了一些非常愚蠢的东西,需要一些新鲜的眼光,但我希望我对这段关系的理解可能是一团糟。
这是我的迁移:
_create_api.exs
defmodule App.Repo.Migrations.CreateApi do
use Ecto.Migration
def change do
create table(:apis) do
add :basePath, :string
add :definitions, :string
add :paths, references(:paths)
timestamps()
end
end
end
_create_paths.exs
defmodule App.Repo.Migrations.CreatePath do
use Ecto.Migration
def change do
create table(:paths) do
add :apis_id, :string
add :route, :string
timestamps()
end
end
end
我的模特:
api.ex
defmodule App.Api do
use App.Web, :model
schema "apis" do
field :basePath, :string
field :definitions, :string
has_many :paths, App.Path, foreign_key: :apis_id
timestamps()
end
end
path.ex
defmodule App.Path do
use App.Web, :model
schema "paths" do
belongs_to :apis, App.Api, references: :apis_id
field :route, :string
timestamps()
end
end
这也是我的 ApiController api_controller.ex
defmodule App.ApiController do
use App.Web, :controller
alias App.Api
def index(conn, _params) do
apis = Repo.all(Api) |> Repo.preload([:paths])
render conn, "index.json", apis: apis
end
end
最后是我的 seeds.ex
alias App.Repo
alias App.Path
alias App.Api
api = %Api{
basePath: "v1",
definitions: "none",
paths: [
%Path{
apis_id: 1,
route: "/account"
}
]
}
Repo.insert! api
如果我删除 %Path 映射并将其设为空字符串,这将起作用。
如能提供正确方向的帮助,我们将不胜感激!
提前致谢。
您不应该将对 paths
的引用放入数据库中。一对多的关系只是单方面的——你只需要在 Path
模式中使用 api_id
,反之则不需要。
但是 Ecto
能够将 Path
s 映射到 Api
结构中的字段。您不需要的是 _create_api
迁移中的 paths
字段。
所以我认为正确的文件内容应该是:
_create_api.exs
defmodule App.Repo.Migrations.CreateApi do
use Ecto.Migration
def change do
create table(:apis) do
add :basePath, :string
add :definitions, :string
timestamps()
end
end
end
_create_paths.exs
defmodule App.Repo.Migrations.CreatePath do
use Ecto.Migration
def change do
create table(:paths) do
add :api_id, references(:apis)
add :route, :string
timestamps()
end
end
end
api.ex
defmodule App.Api do
use App.Web, :model
schema "apis" do
field :basePath, :string
field :definitions, :string
has_many :paths, App.Path
timestamps()
end
end
path.ex
defmodule App.Path do
use App.Web, :model
schema "paths" do
belongs_to :api, App.Api
field :route, :string
timestamps()
end
end
请注意,我从模型中删除了 references
和 foreign_key
。此外,我将字段名称 apis_id
更改为 api_id
以匹配标准命名。
编辑: 添加了 seeds.exs
alias App.Repo
alias App.Path
alias App.Api
api = Repo.insert! %Api{
basePath: "v1",
definitions: "none"
}
path = Repo.insert! %Path{
api_id: api.id,
route: "/account"
}
但我建议你使用变更集。
我首先尝试用一个简单的一层深度结构为我的数据库播种,效果很好。但是,当我添加一个路径映射以匹配我的顶级结构路径字段时,我得到了错误。
** (Postgrex.Error) ERROR 42703 (undefined_column): column "apis_id" of relation "paths" does not exist
我已经尝试删除 apis_id 但我相信我需要该字段来预加载我的 ApiController 中的 Path 结构。也许问题出在我的 has_many
/belongs_to
语法上,尽管我相信我的语法是正确的,并且我已经尝试淹没其他 foreign_keys 和引用但没有运气。
我也可能只是遗漏了一些非常愚蠢的东西,需要一些新鲜的眼光,但我希望我对这段关系的理解可能是一团糟。
这是我的迁移:
_create_api.exs
defmodule App.Repo.Migrations.CreateApi do
use Ecto.Migration
def change do
create table(:apis) do
add :basePath, :string
add :definitions, :string
add :paths, references(:paths)
timestamps()
end
end
end
_create_paths.exs
defmodule App.Repo.Migrations.CreatePath do
use Ecto.Migration
def change do
create table(:paths) do
add :apis_id, :string
add :route, :string
timestamps()
end
end
end
我的模特: api.ex
defmodule App.Api do
use App.Web, :model
schema "apis" do
field :basePath, :string
field :definitions, :string
has_many :paths, App.Path, foreign_key: :apis_id
timestamps()
end
end
path.ex
defmodule App.Path do
use App.Web, :model
schema "paths" do
belongs_to :apis, App.Api, references: :apis_id
field :route, :string
timestamps()
end
end
这也是我的 ApiController api_controller.ex
defmodule App.ApiController do
use App.Web, :controller
alias App.Api
def index(conn, _params) do
apis = Repo.all(Api) |> Repo.preload([:paths])
render conn, "index.json", apis: apis
end
end
最后是我的 seeds.ex
alias App.Repo
alias App.Path
alias App.Api
api = %Api{
basePath: "v1",
definitions: "none",
paths: [
%Path{
apis_id: 1,
route: "/account"
}
]
}
Repo.insert! api
如果我删除 %Path 映射并将其设为空字符串,这将起作用。
如能提供正确方向的帮助,我们将不胜感激!
提前致谢。
您不应该将对 paths
的引用放入数据库中。一对多的关系只是单方面的——你只需要在 Path
模式中使用 api_id
,反之则不需要。
但是 Ecto
能够将 Path
s 映射到 Api
结构中的字段。您不需要的是 _create_api
迁移中的 paths
字段。
所以我认为正确的文件内容应该是:
_create_api.exs
defmodule App.Repo.Migrations.CreateApi do
use Ecto.Migration
def change do
create table(:apis) do
add :basePath, :string
add :definitions, :string
timestamps()
end
end
end
_create_paths.exs
defmodule App.Repo.Migrations.CreatePath do
use Ecto.Migration
def change do
create table(:paths) do
add :api_id, references(:apis)
add :route, :string
timestamps()
end
end
end
api.ex
defmodule App.Api do
use App.Web, :model
schema "apis" do
field :basePath, :string
field :definitions, :string
has_many :paths, App.Path
timestamps()
end
end
path.ex
defmodule App.Path do
use App.Web, :model
schema "paths" do
belongs_to :api, App.Api
field :route, :string
timestamps()
end
end
请注意,我从模型中删除了 references
和 foreign_key
。此外,我将字段名称 apis_id
更改为 api_id
以匹配标准命名。
编辑: 添加了 seeds.exs
alias App.Repo
alias App.Path
alias App.Api
api = Repo.insert! %Api{
basePath: "v1",
definitions: "none"
}
path = Repo.insert! %Path{
api_id: api.id,
route: "/account"
}
但我建议你使用变更集。