Приоритет PostgreSQL при выполнении запросов с помощью ILIKE - PullRequest
1 голос
/ 31 июля 2011

Два светильника:

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

Все тесты пройдены, кроме той, которая выполняет тест на «Джон Доу». На самом деле это в конечном итоге приводит к «Джейн Доу».

Я думаю, что есть какая-то проблема с приоритетом вызова двух ИЛИ перед соседним И, но имеет ли смысл то, чего я пытаюсь достичь?

Я пока не в том месте, где я рефакторинг; просто пытаюсь добраться до зеленого, чтобы я мог двигаться вперед. Спасибо за любую помощь заранее!

1 Ответ

3 голосов
/ 31 июля 2011

Вам нужна небольшая реорганизация, чтобы получить логику, которую вы ищете:

conditions = "
  (firstname ILIKE ? AND lastname ILIKE ?)
  OR
  (firstname ILIKE ? AND lastname ILIKE ?)",
  first_word, second_word, second_word, first_word

Это должно соответствовать как "Джон Доу" и "Доу Джон", но не "Джейн Доу", когда вы звоните:

Contact.search('Jo Do')

В действительности вам не нужны скобки, потому что И имеет более высокий приоритет, чем ИЛИ в булевой алгебре (а логика SQL на основе булевой алгебры )но нет веских причин не включать их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...