两个固定装置:
one:
firstname: John
lastname: Doe
user_id: 1
two:
firstname: Jane
lastname: Doe
user_id: 1
在我的单元测试中,我有以下内容:
test "Searching for a contact gets the right person" do
search = Contact.search("John")
assert_equal 1, search.count
search = Contact.search("Doe")
assert_equal 2, search.count
search = Contact.search("John Doe")
assert_equal 1, search.count
search = Contact.search("John ")
assert_equal 1, search.count
search = Contact.search("Doe John")
assert_equal 1, search.count
end
...最后是我的模型,它调用搜索方法如下所示:
def self.search(search)
# Check if the search query has more than one word
search_split = search.split(" ")
if search_split.count > 1
# User must be searching for a first and last name
first_word = '%' + search_split[0] + '%'
second_word = '%' + search_split[1] + '%'
conditions = "
firstname ILIKE ? OR lastname ILIKE ?
AND
firstname ILIKE ? OR lastname ILIKE ?",
first_word, first_word, second_word, second_word
where(conditions)
else
# Just searching for a first OR last name
# Strip any whitespace
str = search_split[0]
query = '%' + str + '%'
conditions = "firstname ILIKE ? OR lastname ILIKE ?", query, query
where(conditions)
end
end
除了对“John Doe”进行测试的测试之外,所有测试都通过了。它实际上最终也拉动了“Jane Doe”。
我认为在相邻的 AND 之前调用两个 OR 存在某种优先级问题,但这对我要完成的事情有意义吗?
我还没有到重构的地步;只是想变绿,这样我才能前进。提前感谢您的帮助!
最佳答案
您需要进行一些重组才能获得您所追求的逻辑:
conditions = "
(firstname ILIKE ? AND lastname ILIKE ?)
OR
(firstname ILIKE ? AND lastname ILIKE ?)",
first_word, second_word, second_word, first_word
当您调用时,它应该同时匹配“John Doe”和“Doe John”,但不匹配“Jane Doe”:
Contact.search('Jo Do')
您实际上不需要括号,因为 AND has a higher precedence than OR在 bool 代数中(SQL 的逻辑是 based on Boolean Algebra ),但没有充分的理由不包括它们。
关于ruby-on-rails - 使用 ILIKE 查询时的 PostgreSQL 优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6886800/