Ecto:如何在更新中调用函数
Ecto: how to call a function in an update
我正在尝试创建一个迁移,通过对该列中的每个项目调用函数 date_str_to_timestamp
(在同一文件中定义)将列中的数据转换为不同的格式。
from(p in "posts",
update: [set: [ timestamp: ^date_str_to_timestamp(p.time) ]])
|> Pesterbot.Repo.update_all([])
然而我得到这个:
_build/dev/lib/pesterbot/priv/repo/migrations/20170414014413_posts_to_messages.exs:34
** (Ecto.Query.CompileError) `^(p.time(), date_str_to_timestamp)` is not a valid query expression.
* If you intended to call a database function, please check the documentation
for Ecto.Query to see the supported database expressions
* If you intended to call an Elixir function or introduce a value,
you need to explicitly interpolate it with ^
(ecto) expanding macro: Ecto.Query.update/3
_build/dev/lib/pesterbot/priv/repo/migrations/20170414014413_posts_to_messages.exs:33: Pesterbot.Repo.Migrations.PostsToMessages.up/0
(ecto) expanding macro: Ecto.Query.from/2
_build/dev/lib/pesterbot/priv/repo/migrations/20170414014413_posts_to_messages.exs:33: Pesterbot.Repo.Migrations.PostsToMessages.up/0
(elixir) expanding macro: Kernel.|>/2
_build/dev/lib/pesterbot/priv/repo/migrations/20170414014413_posts_to_messages.exs:35: Pesterbot.Repo.Migrations.PostsToMessages.up/0
编辑:@Dogbert
要求的 date_str_to_timestamp
来源
def date_str_to_timestamp(date_str) do
{:ok, datetime} = Timex.parse(date_str, "{UNIX}")
datetime |> Elixir.DateTime.to_unix(:millisecond)
end
end
编辑:
timestamp
将是自相应 time
值的纪元以来的毫秒整数,现在是 UNIX 格式的字符串,例如:Mon Mar 20 19:49:43 CDT 2017
所以Mon Mar 20 19:49:43 CDT 2017
应该变成1490057383000
您不能在这样的 UPDATE
查询中调用 Elixir 函数,因为数据库必须能够计算表达式本身。幸运的是,PostgreSQL 确实有函数可以完成你的 Elixir 函数所做的事情:
iex(1)> A.date_str_to_timestamp "Tue Mar 5 23:25:19 PST 2013"
1362554719000
postgres=# select EXTRACT(EPOCH FROM 'Tue Mar 5 23:25:19 PST 2013'::timestamp) * 1000;
?column?
---------------
1362525919000
(1 row)
您可以像这样在 UPDATE
查询中使用它:
from(p in "posts",
update: [set: [timestamp: fragment("EXTRACT(EPOCH FROM ?::timestamp) * 1000", p.time)]])
我正在尝试创建一个迁移,通过对该列中的每个项目调用函数 date_str_to_timestamp
(在同一文件中定义)将列中的数据转换为不同的格式。
from(p in "posts",
update: [set: [ timestamp: ^date_str_to_timestamp(p.time) ]])
|> Pesterbot.Repo.update_all([])
然而我得到这个:
_build/dev/lib/pesterbot/priv/repo/migrations/20170414014413_posts_to_messages.exs:34
** (Ecto.Query.CompileError) `^(p.time(), date_str_to_timestamp)` is not a valid query expression.
* If you intended to call a database function, please check the documentation
for Ecto.Query to see the supported database expressions
* If you intended to call an Elixir function or introduce a value,
you need to explicitly interpolate it with ^
(ecto) expanding macro: Ecto.Query.update/3
_build/dev/lib/pesterbot/priv/repo/migrations/20170414014413_posts_to_messages.exs:33: Pesterbot.Repo.Migrations.PostsToMessages.up/0
(ecto) expanding macro: Ecto.Query.from/2
_build/dev/lib/pesterbot/priv/repo/migrations/20170414014413_posts_to_messages.exs:33: Pesterbot.Repo.Migrations.PostsToMessages.up/0
(elixir) expanding macro: Kernel.|>/2
_build/dev/lib/pesterbot/priv/repo/migrations/20170414014413_posts_to_messages.exs:35: Pesterbot.Repo.Migrations.PostsToMessages.up/0
编辑:@Dogbert
要求的date_str_to_timestamp
来源
def date_str_to_timestamp(date_str) do
{:ok, datetime} = Timex.parse(date_str, "{UNIX}")
datetime |> Elixir.DateTime.to_unix(:millisecond)
end
end
编辑:
timestamp
将是自相应 time
值的纪元以来的毫秒整数,现在是 UNIX 格式的字符串,例如:Mon Mar 20 19:49:43 CDT 2017
所以Mon Mar 20 19:49:43 CDT 2017
应该变成1490057383000
您不能在这样的 UPDATE
查询中调用 Elixir 函数,因为数据库必须能够计算表达式本身。幸运的是,PostgreSQL 确实有函数可以完成你的 Elixir 函数所做的事情:
iex(1)> A.date_str_to_timestamp "Tue Mar 5 23:25:19 PST 2013"
1362554719000
postgres=# select EXTRACT(EPOCH FROM 'Tue Mar 5 23:25:19 PST 2013'::timestamp) * 1000;
?column?
---------------
1362525919000
(1 row)
您可以像这样在 UPDATE
查询中使用它:
from(p in "posts",
update: [set: [timestamp: fragment("EXTRACT(EPOCH FROM ?::timestamp) * 1000", p.time)]])