ActiveRecord OR查询与SQL中的两个范围,其中一个范围有一个连接
问题描述:
我想编写一个查询,结合两个范围与“OR”查询(使用Rails 4,虽然问题仍然存在与rails 5)。ActiveRecord OR查询与SQL中的两个范围,其中一个范围有一个连接
型号1
scope :association_has_email, -> { joins(:model2).where.not(model2s:{email:nil}) }
scope :description_has_email, -> { where("description ~* ?", email_regex) }
(其中email_regex是一个正则表达式挑选出一个邮件)。
这给了我们SQL LIKE:
SELECT \"model1s\".* FROM \"model1s\" WHERE (description ~* '[[:<:]][A-Z0-9._%+-][email protected][A-Z0-9.-]+.[A-Z]{2,4}[[:>:]]')
SELECT \"model1s\".* FROM \"model1s\" INNER JOIN \"model2s\" ON \"model2s\".\"id\" = \"model1s\".\"model2_id\" WHERE (\"model2s\".\"email\" IS NOT NULL)
创建范围,挑选出这些机会,其中任一电子邮件是在联想或在文本嵌入的电子邮件。
如何编写一个“OR”查询,其中一方需要连接而另一方不需要?
答
确定。 对于导轨4,在那里,或宝石提供一种用于产生或查询,在导轨5的修复,但是如果传递的范围你上面结束了一个
ArgumentError: Relation passed to #or must be structurally compatible
可以使用以下:
scope :email_somewhere, -> { association_has_email.or(Model1.joins(:model2).description_has_email }
SELECT \"model1s\".* FROM \"model1s\" INNER JOIN \"model2s\" ON \"model2s\".\"id\" = \"model1s\".\"model2_id\" WHERE ((\"model2s\".\"email\" IS NOT NULL) OR (description ~* '[[:<:]][A-Z0-9._%+-][email protected][A-Z0-9.-]+.[A-Z]{2,4}[[:>:]]'))
工程,但它会排除任何在描述中有电子邮件但没有model2的东西,因为它使用内部连接。
但是通过使用includes,您可以获得所需的结果。
scope :association_has_email, -> { includes(:model2).where.not(model2s:{email:nil}) }
scope :description_has_email, -> { where("description ~* ?", email_regex) }
意味着你可以使用
scope :email_somewhere, -> { association_has_email.or(Model1.includes(:model2).description_has_email }
的区别是SQL拉所有的属性,从模型1,然后将左外连接的MODEL2查询。
SELECT [...all the model1 attributes...] LEFT OUTER JOIN \"model2s\" ON \"model2s\".\"id\" = \"model1s\".\"model2_id\" WHERE ((\"model2s\".\"email\" IS NOT NULL) OR (description ~* '[[:<:]][A-Z0-9._%+-][email protected][A-Z0-9.-]+.[A-Z]{2,4}[[:>:]]'))
刺激,如果你真的需要使用内部连接的第一个,但我的作品。
请参阅http://*.com/questions/31096009/activerecord-or-query-hash-notation –
使用where-or gem(这是辉煌的......)你会得到一个“ArgumentError:传递给#or的关系必须在结构上兼容“ 但是,如果您向范围传递连接,则会出现问题,如果email_in_description根本不包含model2,则将其排除。 但是,我认为我有一个解决方案。可以通过包括获得一个外部连接... – Carpela
我总是建议人们使用原始SQL,其中ActiveRecord DSL无法成为一个好工具。 – MurifoX