【问题标题】:Activerecord query not returning all resultsActiverecord 查询未返回所有结果
【发布时间】:2014-09-26 08:26:07
【问题描述】:

我在 Rails 4 中遇到 ActiveRecord 查询问题:

我的模型:

class Addressee < ActiveRecord::Base
  has_and_belongs_to_many :emails
end

class Email < ActiveRecord::Base
  belongs_to :author, foreign_key: :from_id, class_name: "Addressee"
  has_and_belongs_to_many :addressees
end

我的 schema.rb

  create_table "addressees", force: true do |t|
    t.string   "token",      limit: nil
    t.string   "domain",     limit: nil
    t.string   "email",      limit: nil
    t.string   "name",       limit: nil
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "addressees_emails", force: true do |t|
    t.integer  "addressee_id"
    t.integer  "email_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

    create_table "emails", force: true do |t|
    t.string   "message_id", limit: nil
    t.integer  "from_id"
    t.string   "subject",    limit: nil
    t.text     "body"
    t.datetime "date"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

我的查询:

# Returns correct emails
query_params = { "addressees.email" => "test@example.com"  }
@emails = Email.includes(:addressees).where(query_params).references(:addressees)

我的问题:

# Returns only the addressee matching the email from query params
@emails.last.addressees
#<ActiveRecord::Associations::CollectionProxy [#<Addressee id: 12, token: "test", domain: "example.com", email: "test@example.com", name: nil, created_at: "2014-09-25 14:06:34", updated_at: "2014-09-25 14:06:34">]>

#Returns the wrong count
@emails.last.addressees.size
#=> 1

#Returns the correct count (because it does a new query)
@emails.last.addressees.count
#=> 3

我的问题:

如何修改查询以包含所有收件人而无需进行其他查询?我将@emails var 传递给我的 json 序列化程序,现在它只包含 1 个收件人而不是全部 3 个。

【问题讨论】:

  • 该查询将地址限制为您使用 LEFT OUTER JOIN 指定的电子邮件。您将不得不重新加载关联以克服这个问题,这需要一个新的查询。这是 ActiveRecord 的限制。您使用的是什么 DBMS?您需要自己编写 SQL。
  • @emails = Email.where('emails.id IN SELECT(email_id FROM addressees_emails WHERE addressee_id IN (SELECT id FROM addressees WHERE email IN (?)))', %w[test@example.com test2@example.com]).includes(:addressees) 我目前无法测试查询,但如果您熟悉 SQL,您应该知道我在哪里使用它。

标签: sql ruby-on-rails activerecord


【解决方案1】:
@emails = Email.where('emails.id IN SELECT(email_id FROM addressees_emails WHERE addressee_id IN (SELECT id FROM addressees WHERE email IN (?)))', %w[test@example.com test2@example.com]).includes(:addressees)

【讨论】:

  • 解释一下会有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多