Монгоидный толчок с апсертом

У меня есть модель User:

class User
  field :username, type: String
  embeds_many :products
end

class Product
  field :name, type: String
  embedded_in :user
end

Я хотел бы иметь одну операцию, которая:

  • вставить пользователя
  • обновить пользователя, если пользователь уже существует (это я могу легко сделать с помощью upsert)
  • продвигать продукты

Это работает для обновления:

User.new(username: 'Hello').upsert

Проблема в том, что при этом будут удалены встроенные продукты (атрибут products не указан).

Могу ли я попросить mongoid пропустить установку массива в пустой? Могу ли я попросить mongoid подтолкнуть новые продукты в конец массива продуктов? Что-то вроде этого:

User.new(username: 'Hello').push(products: [Product.new(name: 'Screen')]).upsert


person Jakub Troszok    schedule 08.12.2015    source источник


Ответы (1)


В конце концов, я закончил тем, что вручную написал следующий запрос:

User.mongo_client[:users].update_one({username: 'Hello'}, 
                                     {"$set" => {first_name: 'Jim', last_name: 'Jones'},
                                      "$pushAll" => [products: [{name: 'Screen'}, {name: 'Keyboard'}]
                                     },
                                     upsert: true)

Где:

  • $ set - это параметры, которые мы хотим установить для данного документа
  • $ pushAll - когда вы используете $ push, вы можете указать только один элемент, $ pushAll позволяет вам добавлять несколько элементов (когда вы указываете только один, он будет вести себя как $ push)
  • upsert - сделает магию вставки / обновления в mongodb

Во втором хэше вы также можете указать $ inc, $ dec, $ pop, $ set и т.д., что весьма полезно.

person Jakub Troszok    schedule 09.12.2015