Rails通过关联记录数进行选择

时间:2019-06-20 23:40:10

标签: sql ruby-on-rails ruby ruby-on-rails-4

我的Rails应用程序中有以下模型:

class Student < ApplicationRecord
  has_many :tickets, dependent: :destroy
  has_and_belongs_to_many :articles, dependent: :destroy

class Article < ApplicationRecord
  has_and_belongs_to_many :students, dependent: :destroy

class Ticket < ApplicationRecord
  belongs_to :student, touch: true

我需要提取所有少于文章的学生,并且我要提取所有最后一个票证标题为“ Something”的学生。

到目前为止,我所做的一切都需要很多时间。我尝试过映射和遍历所有学生。但是我想我需要的是一个联合请求。我正在寻找最有效的方法,因为我正在使用的数据库很大。

3 个答案:

答案 0 :(得分:2)

您问 "I need to extract all Students who has less than articles"。我假设您的意思是"I need to extract all Students who have less than X articles"。在这种情况下,您需要grouphaving https://guides.rubyonrails.org/active_record_querying.html#group

例如Article.group(:student_id).having('count(articles.id) > X').pluck(:student_id)

要解决第二个问题,您可以使用紧急加载https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations来加快代码速度。

result = students.filter do |student|
  students.tickets.last.name == 'Something'
end

答案 1 :(得分:2)

请回答@MCI的第一个问题。但是通过学生记录执行filter / select / find_all或其他任何操作(尽管我还没有听说过ruby中的过滤方法)需要进行n次查询,其中n是学生记录的数量(称为n + 1查询)。

const coll = document.getElementsByClassName("collapsible");
var i;
const ClickEvt = new Event('click'); // prepare click event object

for (i = 0; i < coll.length; i++) 
{
  coll[i].addEventListener("click", function ()
  {
    this.classList.toggle("active");
    var content = this.nextElementSibling;
    if (content.style.maxHeight) {
      content.style.maxHeight = null;
    } else {
      content.style.maxHeight = content.scrollHeight + "px";
    }
  });
  coll[i].dispatchEvent(ClickEvt); // first click event (new line to add)
}

答案 2 :(得分:1)

这里的关联是HABTM,因此下面的查询应该有效

x = 10
Student.joins(:articles).group("articles_students.student_id").having("count(articles.id) < ?",x)