我有一个用户表,如:
email | username
---------------+----------
123@321.com |
123@123.com |
haha@haha.com |
Run Code Online (Sandbox Code Playgroud)
我想username逐个email字段更新,只需将emailbefore切片@。
email | username
---------------+----------
123@321.com | 123
123@123.com | 123
haha@haha.com | haha
Run Code Online (Sandbox Code Playgroud)
我尝试使用以下迁移:
defmodule MyApp.Repo.Migrations.AddDefaultUsernameForUsers do
use Ecto.Migration
import Ecto.Query
def up do
from(u in MyApp.User, update: [set: [username: String.split(u.email, "@") |> List.first ]])
|> MyApp.Repo.update_all([])
end
def down do
MyApp.Repo.update_all(MyApp.User, set: [username: nil])
end
end
Run Code Online (Sandbox Code Playgroud)
但是在运行迁移时,我收到以下错误:
$ mix ecto.migrate
** (Ecto.Query.CompileError) `List.first(String.split(u.email(), "@"))` is not a valid query expression
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?
@Justin Wood 已经解释了为什么不能在更新查询中使用 Elixir 函数,所以我不会重复。在 PostgreSQL 中,您可以在@使用substring带有正则表达式的函数之前提取文本,这将适用于更新查询。这将比加载记录然后一一更新它们要快得多,但如果不调整 SQL 片段,将无法与其他数据库引擎一起使用:
from(u in MyApp.User,
update: [set: [username: fragment("substring(? from '^(.*?)@')", u.email)]])
|> MyApp.Repo.update_all([])
Run Code Online (Sandbox Code Playgroud)
postgres=# select substring('123@321.com' from '^(.*?)@');
substring
-----------
123
(1 row)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2341 次 |
| 最近记录: |