问题
我有一个Post
和Comment
,我想选择帖子,并在包含OR
和具有2个IN
条件的Comment上使用.joins()
和.where()
。
我想要一个生成这个的东西:
SELECT * FROM posts
INNER JOIN comments ON comments.post_id = posts.id
WHERE comments.id IN (1,2,3) OR comments.user_id IN (4,5,6)
我会使用.or()
方法,但它不能使用哈希。
Post.joins(Comment)
.where({ comments: { id: [1, 2, 3] } })
.or({ comments: { user_id: [4, 5, 6] } }) # <-- raises exception
可能的解决方案
为了便于阅读,我对其进行了简化。事实上,我需要这一点来跨数据库适配器工作,所以我会使用Comment.connection.quote_table_name
和Comment.connection.quote_column_name
来正确引用表名和列名。
ids = [1,2,3]
user_ids = [4,5,6]
clause = ""
clause += Comment.sanitize_sql_for_conditions(["comments.id IN (?)", ids]) if ids.any?
clause += " OR " if ids.any? and user_ids.any?
clause += Comment.sanitize_sql_for_conditions(["comments.user_id IN (?)", user_ids]) if user_ids.any?
Post.joins(Comment).where(clause)
问题
这是有效的,但似乎应该有更好的方法。。。有吗?
我假设您的Post
类与has_many :comments
有注释关系,Rails非常聪明,知道当您使用带有关系名称的.where
时,您会考虑每个注释的id,然后您可以简单地编写id。
要使用OR,您必须使用将用于构造主查询的同一类,它就像OR中的"子查询",就像follow。
请尝试使用下一个代码:
Post.joins(:comments)
.where(comments: [1, 2, 3])
.or(Post.where('comments.user_id IN ?', [4, 5, 6]))
轨道或:https://zaiste.net/rails_5_or_operator_active_record/
联接:https://apidock.com/rails/ActiveRecord/QueryMethods/joins
编辑:
由于这个答案引用了已知的问题,您应该使用原始SQL,如follow。
Post.joins(:comments)
.where('comments.id in ? OR comments.user_id in ?', [1, 2, 3], [4, 5, 6])
原始sql中的每个?
都将替换为按相同顺序从左到右传递给.where
的参数。