【问题标题】:Possible to write an Ecto query that unions multiple tables without writing raw SQL?可以编写一个联合多个表而不编写原始 SQL 的 Ecto 查询吗?
【发布时间】:2020-09-03 07:10:25
【问题描述】:

背景:

我正在编写一个简单的问答网站。与 Stackoverflow 非常相似,在此站点中,用户可以对问题、答案或评论点赞/点赞。

问题:

我正在努力编写一个 Ecto 查询,该查询可以返回用户喜欢/支持的所有问题、答案或 cmets。

具体来说,我想写一个查询:

  1. 将特定用户投票支持的所有问题、cmets 和答案作为单个列表返回
  2. 问题、答案和 cmets 的列表按投票时间排序

这个查询似乎需要UNION,据我了解是not yet supported by ecto 2.0

因此,我想知道是否有人可以向我展示或指出我在 Ecto 中处理此类查询的正确方向。感谢您的任何帮助。

以下是相关模型的架构。

...

schema "users" do
  ...

  has_many :answer_upvotes, AnswerUpvote
  has_many :comment_upvotes, CommentUpvote
  has_many :question_upvotes, QuestionUpvote

  many_to_many :upvoted_answers, Answer, join_through: AnswerUpvote
  many_to_many :upvoted_comments, Comment, join_through: CommentUpvote
  many_to_many :upvoted_questions, Question, join_through: QuestionUpvote

  timestamps
end

...

schema "answer_upvotes" do
  belongs_to :answer, Answer
  belongs_to :user, User

  timestamps
end

...

schema "comment_upvotes" do
  belongs_to :comment, Comment
  belongs_to :user, User

  timestamps
end

...

schema "question_upvotes" do
  belongs_to :question, Question
  belongs_to :user, User

  timestamps
end

...

schema "questions" do
  ...   

  belongs_to :user, User

  has_many :answers, Answer
  has_many :upvotes, QuestionUpvote

  many_to_many :upvoting_users, User, join_through: QuestionUpvote

  timestamps
end

...

schema "answers" do
  ...

  belongs_to :question, Question
  belongs_to :user, User

  has_many :comments, Comment
  has_many :upvotes, AnswerUpvote

  many_to_many :upvoting_users, User, join_through: AnswerUpvote

  timestamps
end

...

schema "comments" do
  ...

  belongs_to :answer, Answer
  belongs_to :user, User

  has_many :upvotes, CommentUpvote

  many_to_many :upvoting_users, User, join_through: CommentUpvote

  timestamps
end

编辑

我可以编写一个查询来按问题、答案或项目的投票日期单独排序。

例如:

upvoted_answers_query =
  from answer in Answer,
    join: upvote in assoc(answer, :upvotes), where: upvote.user_id == ^user.id,
    order_by: upvote.inserted_at
    select: answer

但我不知道如何编写一个单独的 Ecto 查询,该查询可以检索用户所有赞成的问题、答案和 cmets,而无需使用联合或编写原始 SQL。

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    Ecto v3.0.0 (2018-10-29) 增加了对 unionunion_all 的支持。

    来自文档的示例:

    supplier_query = from s in Supplier, select: s.city
    from c in Customer, select: c.city, union: ^supplier_query
    

    https://hexdocs.pm/ecto/Ecto.Query.html#union/2

    【讨论】:

      【解决方案2】:

      目前不支持,但有一个开放的票证:https://github.com/elixir-ecto/ecto/issues/1549

      【讨论】:

      • 感谢您指点我打开的票。我想除了编写原始 SQL 查询并执行它之外,还没有解决方法来联合?
      • 是的 - 虽然如果你这样做基准测试 - 在很多情况下,运行单独的查询并将它们 ++ 在一起会更快 thing = blah_blah |> Repo.all |> Kernel.++ ( blah_blah_blah |> 回购.all )
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      • 1970-01-01
      • 2019-07-25
      相关资源
      最近更新 更多