ecto-将表列迁移到其自己的联接表中将数据移至新表

问题描述

我想从这里出发:

  schema "products" do
    field :name,:string
    field :brand,:string
    ...more fields...
  end

对此:

  schema "products" do
    field :name,:string
    ...more fields...
  end

  schema "brands" do
    field :name,:string
    ...more fields...
  end

  schema "product_brand_joins" do
    field :p_id,:integer
    field :b_id,:integer
    ...more fields...
  end

在不丢失具有包含:brand字段字符串的产品的当前数据的情况下。

我了解如何创建新的brands表和product_brand_joins表,以及如何通过ecto迁移从product表中删除“:brand”。但是有没有办法将我当前的数据处理到新表中?

解决方法

您可以使用execute/1 function setErrorFor(input,message) { const formControl = input.parentElement; // .form-control const small = formControl.querySelector('small'); // add error message inside small small.innerText = message; // add errror class formControl.className = 'form-control error'; } 函数执行SQL语句,其中接受两个参数的是第一个的可回滚版本,该版本希望语句在迁移时执行,而一个在执行回滚时。

因此,您可以使用它来定义迁移时应该发生的事情,这成为定义语句的问题。 this docs page from PostgreSQL的末尾有一个基于子查询插入的示例,我们将在此处使用它。

在您的迁移execute/2文件中:

.exs

然后对于回滚,您将在迁移中实现use Ecto.Migration def up do create table(:brands) do add :name,:string,# add other fields end create table("product_brand_joins") do add :product_id,references: :products add :brand_id,references: :brands end # Insert into the brands table a brand with each name found in products execute( "INSERT INTO brands(name) SELECT DISTINCT(brand) FROM products" ) # Insert into the joined table the product and brand ids execute( "INSERT INTO product_brand_joins(product_id,brand_id) SELECT p.id,b.id FROM products p LEFT JOIN brands b ON p.brand = b.name" ) # And finally delete the column from products alter table(:products) do remove :brand end end 函数,以使用类似的逻辑来还原该过程:在down中创建brand列,并根据相应的品牌名称进行填充在产品ID上,然后删除新表。