查询返回的空关联与NOT IN()和IN()

时间:2018-10-26 14:35:21

标签: ruby-on-rails ruby postgresql postgresql-9.5

我有模型InvitationPerson。这个问题中重要的属性和关系如下:

# has sponsor_id, referral_email
class Invitation < ApplicationRecord
  belongs_to :sponsor, class_name: 'Person'
  belongs_to :referral, class_name: 'Person',
                        foreign_key: :referral_email, primary_key: :email
  scope :pending, -> { where.not(referral_email: Person.select(:email).distinct) }
end

# has id, email
class Person < ApplicationRecord
  has_many :sent_invitations, class_name: 'Invitation', 
                              foreign_key: :sponsor_id
  has_many :received_invitations, class_name: 'Invitation', 
                                  foreign_key: referral_email, 
                                  primary_key: :email
  has_many :referrals, class_name: 'Persona', through: :sent_invitations
  has_many :sponsors, class_name: 'Persona', through: :received_invitations
end

我找到了一条记录Invitation,它的referral_email在表Person中不存在,并且它的sponsor_id是有效的Person。 / p>

场景::我尝试从@sponsor看它有多少sent_invitations.pending,但是查询返回的是空关系:

@sponsor.sent_invitations.pending.count # => 0

但这是我在尝试调试时运行的其他查询的结果:

@sponsor.sent_invitations.count # => 1
@sponsor.referrals.count # => 0
@sponsor.sent_invitations.first.referral_email # => 'some_email@example.com'
Person.pluck(:email).include? @sponsor.sent_invitations.first.referral_email # => false

我将scope的{​​{1}}的条件反转为:

Invitation

但是预期的查询不断返回空关系

scope :pending, -> { where(referral_email: Person.select(:email).distinct) }

有人知道发生了什么事吗?

代码在测试中工作正常,我们在生产中发现了这个问题。

查询

查询原始尝试

@person.sent_invitations.pending.count # => 0

第二次尝试查询

SELECT "invitations".* FROM "invitations" WHERE "invitations"."sponsor_id" = $1 AND ("invitations"."referral_email" NOT IN (SELECT DISTINCT "person"."email" FROM "person"))

1 个答案:

答案 0 :(得分:0)

Persona中有一些记录带有email: nil。删除它们可使查询按预期方式工作:

@person.sent_invitations.pending.count # => 1
@person.sent_invitations.first.referral_email # => 'some_email@example.com'
@person.sent_invitations.pending.first.referral_email # => 'some_email@example.com'

scope保持原始状态:

scope :pending, -> { where.not(referral_email: Persona.select(:email).distinct) }

我将研究为什么nil电子邮件会导致这种行为。感谢您的帮助。

相关问题