[英]Rails Active Record Queries - Not Equal and Blank/Empty Strings
I have an active record query with a Not Equal clause for a string.我有一个活动记录查询,其中包含一个字符串的 Not Equal 子句。 For example:
例如:
Post.where.not(title: "Rails 4")
or或者
Post.where("title != ?", "Rails 4")
However, if the title is empty or blank it will not be included in the results.但是,如果标题为空或空白,则不会包含在结果中。 How can I also include the records that have a blank or empty title?
我怎样才能同时包含标题为空或空的记录?
For example:例如:
Posts帖子
id => 1, title => "Rails 4"
id => 2, title => ""
id => 3, title => "Rails 3"
Actual Result:实际结果:
Post.where.not(title: "Rails 4") #=> [3]
Desired Result:期望的结果:
Post.where.not(title: "Rails 4") #=> [2, 3]
试试下面的查询
Post.where("title != ? OR title = ?", "Rails 4",'')
* NOTE I'm assuming you're using a database like postgres and that the issue you're having is with null values, not empty string values. *注意我假设您正在使用像 postgres 这样的数据库,并且您遇到的问题是 null 值,而不是空字符串值。 If empty string values aren't being returned then you have an entirely different issue
如果没有返回空字符串值,那么你有一个完全不同的问题
The reason where.not(title: 'Rails 4')
doesn't return what you expect is that you have null values in the string field, and any comparison with null will be null, which is falsey. where.not(title: 'Rails 4')
没有返回您期望的结果的原因是您在字符串字段中有 null 个值,并且与 null 的任何比较都将是 null,这是错误的。
Posts帖子
id => 1, title => "Rails 4"
id => 2, title => ""
id => 3, title => "Rails 3"
id => 4, title => NULL
In order to include Post #4 in the results, you need to explicitly include null values.为了在结果中包含 Post #4,您需要明确包含 null 个值。 One way to do that is with
IS NULL
.一种方法是使用
IS NULL
。
# Original - excludes rows with null title
Post.where.not(title: "Rails 4") #=> [2,3]
# SELECT posts.* FROM posts WHERE posts.title != 'Rails 4'
# Option #1 - explicitly include null
Post.where.not(title: "Rails 4").or(Post.where(email: nil)) #=> [2,3,4]
# SELECT posts.* FROM posts WHERE (posts.title != 'Rails 4' OR posts.title IS NULL)
# Option #2 - replace null values with empty string
POST.where.not("coalesce(posts.title, '') = ?", 'Rails 4')
# SELECT posts.* FROM posts WHERE NOT (coalesce(posts.title, '') = 'Rails 4')
A third solution is to disallow null values in your string field entirely (with a NOT NULL
constraint).第三种解决方案是完全禁止字符串字段中的 null 值(具有
NOT NULL
约束)。 Allowing null values in a string field can have other unexpected side-effects - for example, if you order your posts by 'email' then posts with a null email will show up in a different spot than you posts with an empty string email, but to the user it just looks confusing.在字符串字段中允许 null 值可能会产生其他意想不到的副作用 - 例如,如果您通过“电子邮件”订购帖子,那么带有 null email 的帖子将显示在与带有空字符串 email 的帖子不同的位置,但是对用户来说,它看起来很混乱。
You can manually type the SQL here and possibly create a database dependency, or use ActiveRecord combined with Arel , which is a bit less readable, but works nicely: 您可以在此处手动键入SQL并可能创建数据库依赖项,或者将ActiveRecord与Arel结合使用,后者可读性较差,但运行良好:
table = Post.arel_table
Post.where(table[:title].not_eq('Rails 4').or(table[:title].eq('')))
Pavans答案是正确的,只需使用它
Post.where("title != ? OR title = ?", "Rails 4",'')
I realise this is 7 years old but it still comes up on Google.我意识到这已经 7 年了,但它仍然出现在谷歌上。 A better solution is using reject instead of where.not
更好的解决方案是使用 reject 而不是 where.not
Post.all.reject{|x| x.title == "Rails 4"}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.