Активная запись, где не логическое значение: правда - PullRequest
3 голосов
/ 26 марта 2019

Я изо всех сил пытаюсь сосредоточиться на запросе ActiveRecord.

Я пытаюсь найти в моей базе данных объекты GolfRetailer с идентификатором 1..100, которые имеют что-то (не nil) в своем поле :website, и которые не имеют true вих duplicate_domain поле.

Вот запрос, который я ожидал выполнить:

GolfRetailer.where.not(website: nil, duplicate_domain: true).where(id: 1..100)

Я также пробовал этот вариант по существу того же запроса: GolfRetailer.where.not(website: nil).where(id: 1..100, duplicate_domain: !true)

Но оба возвращают пустой массив, несмотря на то, что определенно существуют записи, отвечающие этим требованиям.

Когда я запускаю GolfRetailer.where.not(website: nil).where(id: 1..100), я получаю массив, и когда я запускаю GolfRetailer.where.not(website: nil, duplicate_domain: nil).where(id: 1..100), я также получаю массив, но со всеми записями, которые do имеют истинный флаг duplicate_domain, который нене то, что я ищу.

Я бы предпочел не искать записи с duplicate_domain: nil, так как это не всегда правильно (возможно, я еще не обработал их домен).

Для ясности, вот схема дляМодель.

create_table "golf_retailers", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "place_id"
    t.string "website"
    t.string "formatted_address"
    t.string "google_places_name"
    t.string "email"
    t.boolean "duplicate_domain"
    t.index ["duplicate_domain"], name: "index_golf_retailers_on_duplicate_domain"
  end

Чего мне не хватает, чтобы этот запрос работал?

1 Ответ

5 голосов
/ 26 марта 2019

Это происходит потому, что в SQL при выполнении != TRUE любые значения NULL не будут включены в результат. Это связано с тем, что значение NULL представляет неизвестное значение , поэтому БД не знает, как выполнить какие-либо операции сравнения для неизвестного значения, и поэтому они исключены.

Один из способов обойти это - использовать IS DISTINCT FROM:

GolfRetailer
  .where(id: 1..100)
  .where.not(website: nil)
  .where("duplicate_domain IS DISTINCT FROM ?", true)

Как уже упоминали другие, вы должны также спросить себя, действительно ли это случай, когда вам неизвестно, если у GolfRetailer есть duplicate_domain.

Если все GolfRetailer с duplicate_domain, равным NULL, на самом деле означают, что они не имеют его (false), чем следует подумать о том, чтобы полностью исключить значение NULL для этого столбца.

Это можно сделать, добавив ограничение NOT NULL для столбца с change_column переносом базы данных .

Чтобы добавить ограничение NOT NULL, сначала необходимо убедиться, что все данные в столбце имеют ненулевые значения.

def change
  GolfRetailer.in_batches.update_all(duplicate_domain: false)

  change_column_null :golf_retailers, :duplicate_domain
end

Если ваше приложение находится под нагрузкой, вы также должны быть осторожны с потенциальной производительностью, которую может иметь любая миграция, особенно если вы добавляете ограничение NOT NULL со значением по умолчанию.

Подумайте об использовании чего-то вроде гема Strong Migrations , чтобы помочь найти миграции БД, которые могут вызвать простои перед производством.

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