현재 사용자와 일치하거나 현재 사용자의 투표가있는 기사를 필터링하여 3 번째 쿼리에서 중복 기사를 확실히 피할 수 있습니다.
더 이상적으로 당신이 당신의 주문 요구 사항을 캡슐화하는 단일 쿼리를 수행 할, 당신이 말하는대로,
q = Article.where(article_type: 'public')
# Filter out articles owned by the current user
q = q.where.not(user_id: current_user.id)
# Filter out articles voted on by the current user
# This left joins the votes table to include the single row that will have
# recorded the vote for the current user on the article in question
# if the id of that left joined table is null then we know there
# is no vote on the article for the current user and that it won't have
# been included in the second step
q = q.joins("left join votes on article_id = articles.id and user_id = #{User.sanitize(current_user.id)}"
q = q.where(votes: { id: nil })
articles = q # or q.limit(10) or somesuch
을하거나 할 수는 Article.where(article_type: 'public')
을하고있는 가정. 얼마나 효과적 일지 확신하지 못하기 때문에 시도해 볼 필요가 있습니다. 단일 쿼리를 사용하면 기사를 매기기 쉬워집니다. (복잡한 검색 명령이 실제로 사용자에게 명확한 지 여부와 3 가지 검색을 통해 더 잘 수행 될지 여부를 고려할 수도 있습니다.하지만 이는 또 다른 질문입니다.)
이렇게하려면 약간 더 복잡한 쿼리가 필요하고 좀 더 복잡한 순서가 필요합니다. 나는 당신의 기준에 따라 순서를 설정하는 CASE
을 사용하고 있습니다 :
q = Article.where("user_id = ? or article_type = 'public'", current_user.id)
# As in the query above, join in the vote row for the current user on the article
q = q.joins("left join votes on article_id = articles.id and user_id = #{User.sanitize(current_user.id)}"
q = q.where(votes: { id: nil })
# First order by whether the user is the current user or not
q = q.order("case when articles.user_id = #{User.sanitize(current_user.id)} then 1 else 2 end")
# Next order by whether the user has voted or not
q = q.order("case when votes.id is not null then 1 else 2 end")
articles = q # or q.limit(100) or q.page(1) or somesuch
순서 절에서 case 문으로 조건을 변환 중 1 또는 2 그래서 첫 번째 순서 절에서 예를 들어. 기사의 사용자 ID가 현재 사용자와 일치하면 1
이 정렬에 사용되고 그렇지 않으면 2
이 사용됩니다. 따라서 사용자의 기사는 기사 목록에서 더 높게 나타납니다. 정렬 기준은 사용자가 기사에 투표했는지 여부입니다. 그래서 그것은 order by 1, 1
과 같은 것으로 끝납니다.
원하는대로해야합니다 (테스트하지는 않았으므로 여기 저기 팅겨보고 필요할 수도 있음).
답변 해 주신 Shadwell에게 감사드립니다. 나는 약간 혼란 스럽다. "그 다음에 1 다른 2 끝"은 무엇을합니까? q.where (votes : {id : nil})? 나는 또한 매개 변수를 보내고있다 : 소유자의 사용자 이름과 기사 제목으로 기사를 검색하는 단어. – Moh
'order (...)'에 대소 문자를 설명하는 비트를 추가했습니다. 'votes : {id : nil}'은'votes.id is null'처럼 SQL로 변환됩니다. – Shadwell