0

I've got model User:

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

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

I would like to have single operation that would:

  • insert the user
  • update the user in case the user exists already (this i can easily do with upsert)
  • push the products

This works for upserting:

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

The problem is that this will delete the embedded products (the products attribute is not specified).

Can I ask mongoid to skip setting array to empty? Can I ask mongoid to push new products at the end of products array? Something like this:

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

Jakub Troszok
  • 99,267
  • 11
  • 41
  • 53

1 Answers1

0

Finally I ended up by manually writing the following query:

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

Where:

  • $set - are the params that we want to set for a given document
  • $pushAll - when you use $push you can specify only one element, $pushAll allows you to append multiple elements (when you specify only one it will behave like $push)
  • upsert - will do the insert/update magic in the mongodb

In the second hash you can also specify $inc, $dec, $pop, $set etc... which is quite useful.

Jakub Troszok
  • 99,267
  • 11
  • 41
  • 53