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

Query returning empty association with NOT IN () and with IN ()

我有模型 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 不存在于 table Person 中,而它的 sponsor_id 是有效的 Person.

场景:@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

我将 Invitationscope 的条件反转为以下内容:

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

但是预期的查询一直返回空关系

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

有人知道会发生什么吗?

代码在测试中运行良好,我们在生产中发现了这个问题。

查询

原始try的查询

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

第二次尝试查询

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

table 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 电子邮件会造成这种行为。感谢您的帮助。