gpt4 book ai didi

elixir - Ecto 连接动态构建的条件

转载 作者:行者123 更新时间:2023-12-02 06:33:16 26 4
gpt4 key购买 nike

我正在尝试构建一个带有左连接的 Ecto 查询,并且连接上有可选的额外条件。我将尝试用典型的帖子和评论示例来描述它。

帖子有_很多评论评论属于_帖子。

假设评论有两个 bool 字段:已批准和精选。

我想获取所有帖子,无论它们是否有评论,因此需要左连接。我想要预加载注释,但最好是一个 SQL 查询。我想选择性地过滤有关已批准和推荐的评论。

我正在尝试编写一个类似这样的函数,其中如果批准或特色不为零,则它们将包含在联接中,如果它们为零,则它们将被忽略。我还没有找到比这样更好的方法:

def posts_with_comments(approved, featured, some_var) do
query = Post
|> where([p], p.some_field == ^some_var

cond do
!is_nil(approved) and !is_nil(featured)
-> join(query, :left, [p], c in Comment, [post_id: p.id, approved: ^approved, featured: ^featured])

!is_nil(approved)
-> join(query, :left, [p], c in Comment, [post_id: p.id, approved: ^approved])

!is_nil(featured)
-> join(query, :left, [p], c in Comment, [post_id: p.id, featured: ^featured])

true -> join(query, :left, [p], c in Comment, [post_id: p.id])
end

|> preload([p, c], [comments: c])
|> select([p], p)
|> Repo.all

end

这可行,但必须有更好的方法。如果我有第三个参数,那就太疯狂了。我正在寻找一种方法来动态构建 join()on 参数的列表。由于需要固定,我的尝试失败了。

我无法将这些条件放在 where 中,因为如果我执行 where t.approved == true 之类的操作,我只会收到已批准的帖子评论。

最佳答案

我认为答案是使用dynamic功能。

这有效。 (忽略我之前的 some_var 条件)。

def posts_with_comments(approved, featured) do
query = Post
join(query, :left, [p], c in Comment, ^do_join(approved, featured))
|> preload([p, c], [comments: c])
|> Repo.all
end

defp do_join(approved, featured) do
dynamic = dynamic([p, c], c.post_id == p.id)

dynamic =
case approved do
nil -> dynamic
_ -> dynamic([p, c], ^dynamic and c.approved == ^approved)
end

case featured do
nil -> dynamic
_ -> dynamic([p, c], ^dynamic and c.featured == ^featured)
end
end

这比我的第一次尝试要好得多,因为这是一个简单的串联,随着条件的增加,而不是条件的爆炸,只会变得更长。

作为一个练习,我无法通过向其提供字段列表并使用诸如reduce之类的东西来使其更加通用。我遇到的问题是使字段名称(例如,c.approved)从变量中起作用。

join 似乎支持两种类型的 on 参数。关键字列表(我认为这意味着 ==)和更具表现力的格式。 dynamic 似乎不适用于关键字列表。它尝试将 p.id 扩展为 p.id()。

我无法让 @mudasobwa 的基于宏的解决方案发挥作用。我还不是一个宏专家,但我不明白 nil 匹配如何在运行时工作。

关于宏解决方案的另一件事。由于某种原因,它也不适用于关键字列表。我希望像这样的简单宏能够工作:

defmacrop do_join do
quote do
[post_id: p.id]
end
end

但事实并非如此。它尝试将 p.id 扩展为 p.id()

关于elixir - Ecto 连接动态构建的条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50635661/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com