2016-03-31 5 views
13

Я использую Mongoid в проекте Rails (оба 4.0.x), и у меня есть документ с хэш-полем, в котором хранятся некоторые данные, не содержащие схемы.установка значений полей хеша мангоида

class Thing 
    field :name, type: String 
    field :mass, type: Integer 
    field :info, type: Hash 
end 

С помощью этой установки, я могу запросить вещи, скажем, у которых есть ключ :endDate вроде так:

Thing.where("info.endDate"=>{'$exists'=>true}) 

И это все красиво и удобно. Использование хэш-поля для этого поля :info приятно, потому что то, что я хочу сохранить, не имеет фиксированной схемы и варьируется от одной вещи к другой.

Хорошо, но я не могу использовать тот же синтаксис точек для $set пары ключ/значение в хеше :info. [1]

thing.set("info.endDate"=>Time.now) 

вызывает ошибку Mongoid::Errors::UnknownAttribute.

Это говорит мне, что мне нужно включить Mongoid::Attributes::Dynamic в мою модель, чтобы сделать это, но это не кажется прямо на меня. The point of the hash field type, похоже, позволит вам работать с данными, которые не имеют фиксированной схемы. Кажется, мне не нужно включать специальный модуль «динамических атрибутов» для использования хеш-полей.

Так прямо сейчас, я обновляю значение, используя обычный старый [] синтаксис, а затем вызвать save на модели, например, так:

thing.info[:endDate] = Time.now 
thing.save 

Но много времени это случается, что было бы лучше, до $set значение. Есть ли другой синтаксис для установки значений полей хэша? Я ошибаюсь в отношении вышеупомянутого сообщения об ошибке, а динамические атрибуты ошибочны? Я застрял, делаю обновление на два шага для хэш-полей?

[1] По правде говоря, я недавно перешел из mongomapper, и поэтому мои ожидания в отношении этого синтаксиса частично заданы тем, что он смог сделать это ранее в mongomapper.

+1

Я думаю, что embeds_one, который будет определен как Mongoid :: Атрибуты :: Dynamic, будет работать для вас (никогда не испытанной этот подход) –

+2

Я не Не требуется встроенный документ. Я хочу поле Hash, потому что данные, которые я храню, варьируются от документа к документу. И mongoid дает мне способ запросить конкретные пары ключей/значений внутри этого хэша. Я хотел бы иметь возможность обновлять пары ключ/значение в этом хэше, как легко, используя $ set. – Bee

+0

Разве это не должно быть '.set (: info => {: endDate => Time.now}). Это было некоторое время с тех пор, как я работал с MongoDB. –

ответ

9

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

Нет, вы не застреваете с помощью двухэтапных обновлений для ваших хэшей вообще!

[], [] = являются ярлыками для read_attribute() и write_attribute() и должны использоваться, если вы не указали Mongoid::Attributes::Dynamic. Если вы попытаетесь использовать $set без включения динамических атрибутов, вы получите ошибку no-method, так как не увидите ваши динамические атрибуты в качестве определенных атрибутов.

Если вы прочитаете источник Mongoid::Attributes::Dynamic, вы обнаружите, что это необходимо для добавления функциональности динамических атрибутов.

Чтобы обновить значения, в том числе Mongoid::Attributes::Dynamic вам необходимо выполнить следующие действия:

thing = Thing.first 
thing.set("info.endDate" => Time.now) 
thing.reload # This will update the current variable 

В противном случае, если вам нужно вы можете легко пропустить это и сделать обновление значения по 2-шагового метода

Я надеюсь, это проливает некоторый свет на ваш запрос.

Источник:

Rails mongoid dynamic fields - no method error

Dynamic attributes with Rails and Mongoid

+0

Я до сих пор не удовлетворен этим ответом. Документация по динамическим полям, похоже, относится к динамическому добавлению полей в документ. Похоже, что установка пары ключ/значение в объявленном поле Hash - это то, о чем они говорят, когда речь идет о динамических полях. Какой хороший тип данных Hash, где вы не можете добавить произвольные пары ключ/значение? И на самом деле я могу добавить произвольные значения к хэшу, просто не используя $ set, по-видимому. Но, возможно, я просто спорю с дизайном мангоид здесь. Я не знаю. – Bee

+1

@Bee Я знаю, что кажется, что это не устраивает возможность использовать '$ set', только когда вы хотите его на полях Hash. Как я объяснил в своем ответе, они отключили эту функцию, чтобы использовать '$ set', потому что ее значения могут быть динамическими, и если в коде есть некоторые ошибки, это может привести к непредвиденным полям. Но когда вы используете [], [] = вы уверены, какие значения вы используете. Это именно то, как он был разработан. Но мы можем включить '$ set' для полей Hash, включив этот модуль и сообщая Mongoid, что мы уверены в коде, который мы закодировали. Подумайте с точки зрения автора, и это кажется правильным. –

+1

Отлично! Отлично работает: D –

1

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

Вы можете изменить это, и это будет работать

thing.set("info.endDate", Time.now) 
+0

Спасибо! Но это синтаксис для наборов Mongoid 3.x. Начиная с Mongoid 4.x они переключились на передачу хэша пар полей/значений для установки. – Bee

+0

Да @Bee, на самом деле я использую mongoid 3.x в своем текущем проекте. и да mongoid 4.x, установите аргументы в качестве пары ключ-значение. Спасибо за ваш ответ – Sukanta