簡體   English   中英

Rails 活動記錄查詢 - 不等於和空白/空字符串

[英]Rails Active Record Queries - Not Equal and Blank/Empty Strings

我有一個活動記錄查詢,其中包含一個字符串的 Not Equal 子句。 例如:

 Post.where.not(title: "Rails 4")

或者

 Post.where("title != ?", "Rails 4")

但是,如果標題為空或空白,則不會包含在結果中。 我怎樣才能同時包含標題為空或空的記錄?

例如:

帖子

id => 1, title => "Rails 4"
id => 2, title => ""
id => 3, title => "Rails 3"

實際結果:

Post.where.not(title: "Rails 4") #=> [3]

期望的結果:

Post.where.not(title: "Rails 4") #=> [2, 3]

試試下面的查詢

Post.where("title != ? OR title = ?", "Rails 4",'')

*注意我假設您正在使用像 postgres 這樣的數據庫,並且您遇到的問題是 null 值,而不是空字符串值。 如果沒有返回空字符串值,那么你有一個完全不同的問題

where.not(title: 'Rails 4')沒有返回您期望的結果的原因是您在字符串字段中有 null 個值,並且與 null 的任何比較都將是 null,這是錯誤的。

帖子

id => 1, title => "Rails 4"
id => 2, title => ""
id => 3, title => "Rails 3"
id => 4, title => NULL

為了在結果中包含 Post #4,您需要明確包含 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')

第三種解決方案是完全禁止字符串字段中的 null 值(具有NOT NULL約束)。 在字符串字段中允許 null 值可能會產生其他意想不到的副作用 - 例如,如果您通過“電子郵件”訂購帖子,那么帶有 null email 的帖子將顯示在與帶有空字符串 email 的帖子不同的位置,但是對用戶來說,它看起來很混亂。

您可以在此處手動鍵入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",'')

我意識到這已經 7 年了,但它仍然出現在谷歌上。 更好的解決方案是使用 reject 而不是 where.not

Post.all.reject{|x| x.title == "Rails 4"}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM