gpt4 book ai didi

elixir - 使用 Ecto 一次插入多行。 "protocol Enumerable not implemented for #Ecto.Changeset"

转载 作者:行者123 更新时间:2023-12-01 07:52:03 28 4
gpt4 key购买 nike

我有两张 table 。 topics的表其中has_many tweets .我的表tweets belongs_to topic .

主题架构:

defmodule Sentiment.Topic do
use Sentiment.Web, :model

schema "topics" do
field :title, :string

has_many :tweets, Sentiment.Tweet
end

def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:title])
|> validate_required([:title])
end
end

推文架构:
defmodule Sentiment.Tweet do
use Sentiment.Web, :model

schema "tweets" do
field :message, :string
belongs_to :topic, Sentiment.Topic

end

@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:message])
|> validate_required([:message])
end
end

我试图插入一个 topic进入我的表,然后是 500 tweets在我运行 Twitter 搜索该主题之后。

在我的 Controller 中,我使用 Ecto.Multi对我的 repo 操作进行分组,但是,每次运行我的操作时,我都会收到错误 protocol Enumerable not implemented for #Ecto.Changeset<action: nil, changes: %{message: "\"aloh....
这就是我尝试首先插入我的主题,获取它的 id,然后插入一 strip 有关联 id 的推文消息和一个事务的方式。
 def create(conn, %{"topic" => topic}) do
# create a topic changeset
topic_changeset = Topic.changeset(%Topic{}, topic)

# obtain a list of tweet messages: ["hello", "a tweet", "sup!"]
%{"title" => title} = topic
all_tweets = title
|> Twitter.search

# create an Ecto.Multi struct.
multi =
Ecto.Multi.new
|> Ecto.Multi.insert(:topics, topic_changeset) #insert topic
|> Ecto.Multi.run(:tweets, fn %{topics: topic} ->
changeset_tweets = all_tweets
|> Enum.map(fn(tweet) ->
%{topic_id: topic.id, message: tweet}
end)

Repo.insert_all(Tweet, changeset_tweets)

end)

# Run the transaction
case Repo.transaction(multi) do # ERROR HERE!
{:ok, result} ->
conn
|> put_flash(:info, "Success!")
|> redirect(to: topic_path(conn, :index))
{:error, :topics, topic_changeset, %{}} ->
conn
|> put_flash(:error, "Uh oh...")
|> render("new.html", changeset: topic_changeset)
{:error, :tweets, topic_changeset, %{}} ->
conn
|> put_flash(:error, "Something really bad happened...")
|>render("new.html", changeset: topic_changeset)
end
end

我该怎么办 insert_all使用 Ecto.Multi 在一笔交易中大约有 500 行?

更新
我已将变更集列表转换为 map 列表,而我的错误已更改为更令人困惑的内容。

error
what I am trying to insert

最佳答案

对于 Ecto.Multi 要正确地进行步骤,每个步骤都必须返回 {:ok, value}{:error, reason}元组。

insert ing, update ing 或 delete在变更集中,它会自动返回这样一个元组,但对于 run ,您需要明确返回它。

请考虑以下几点:

Ecto.Multi.new
|> Ecto.Multi.insert(:topics, topic_changeset) #insert topic
|> Ecto.Multi.run(:tweets, fn %{topics: topic} ->
maps =
Enum.map(all_tweets, fn(tweet) ->
%{topic_id: topic.id, message: tweet}
end)

{count, _} = Repo.insert_all(Tweet, maps)
{:ok, count} # <----
end)

关于elixir - 使用 Ecto 一次插入多行。 "protocol Enumerable not implemented for #Ecto.Changeset",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45110119/

28 4 0