Как мне найти массив хэшей на основе нескольких ключей в Rails Postgres? - PullRequest
1 голос
/ 10 апреля 2020

Мне бы хотелось иметь массив хейсов, которые я могу вводить и искать.

add_column :drinkers, :habits, :text, array: true, default: []
drinker.habits << { year: DateTime.now.year, month: DateTime.now.month, drinker_id: drinker_id, napped_at_8am: true }

Как мне искать пьющих по нескольким значениям ключа drinker.habits?

Drinker.select {|drinker| drinker[habits][:year] === 2020 && drinker[habits][:drinker_id] === 1 }

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

1 Ответ

1 голос
/ 10 апреля 2020

Это действительно просто классический c пример стрельбы в ноги с плохим моделированием базы данных.

Postgres массивы - хороший инструмент для действительно специализированных задач, где у вас есть массив простых скалярных значения, такие как целые числа или строки. Они не очень хорошая идея, если вы хотите хранить хэши. Если вы поместите Ruby га sh внутрь столбца массива, вы получите незапрашиваемый беспорядок.

Тип JSON / JSONB может хранить более сложные структуры, такие как массив объектов, и является допустимым выбором. если данные не поддаются какой-либо попытке подтвердить схему. В то время как вы можете запрашивать массив объектов с помощью оператора include:

SELECT *
FROM "drinkers"
WHERE habits @> '[{"year": 2020}]'

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

Вместо этого вы просто хотите столкнуться с фактами, что реляционные базы данных являются табличными и способ моделировать данные в реляционной базе данных - это, как вы уже догадались, таблицы.

class Drinker < ApplicationRecord
  has_many :habits
end

class Habit < ApplicationRecord
  belongs_to :drinker
end

Drinker.joins(:habits)
       .where(habits: { year: 2020 })

TLDR; массив, JSON / JSONB и hstore являются достойными инструментами для действительно специализированных работ. Но никогда не должен быть вашим первым выбором для чего-либо.

...