Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update value of array field using mongoid

I'm trying to find a way to update a single array item using mongoid. I'm using Rails 4 and Mongodb.

My model looks like this

class User
  include Mongoid::Document
  include Mongoid::Timestamps

field :my_book_list, type: Array, default: []
field :book_name, type: String

I'm able to add entry to the array field using the following code:

User.where(id: self.user_id).add_to_set("my_book_list" => self.book_name)

After I have added data to the array, in the database it looks like this

db.collection.users 
{
    "_id" : ObjectId("56e09d54a0d00b0528000001"),
    "status" : true,
    "sign_in_count" : 3,
    "my_book_list" : 
     ["Learning Ruby", "MongoDB for Dummies"]

}

What I'm struggling with is to find a Rails / Mongoid way of updating the value of an item in the array by looking for the name.

Simply put, how do I change the value of my_book_list[1] by searching for it through name and not knowing its index. In this case index 1 is "MongoDB for Dummies" and needs to be updated to "MongoDB". So that the "my_book_list" array field looks like this after its updated:

db.collection.users 
{
    "_id" : ObjectId("56e09d54a0d00b0528000001"),
    "status" : true,
    "sign_in_count" : 3,
    "my_book_list" : 
     ["Learning Ruby", "MongoDB"]

}

How do I achieve this ?

like image 546
Donny Avatar asked Jul 15 '26 03:07

Donny


1 Answers

Instead of updating, think of it as adding & removing. You can use pull (https://docs.mongodb.org/ecosystem/tutorial/mongoid-persistence/#atomic)

Where your add to set uniquely adds it to an array, pull removes it based on the name. So assuming this:

user = User.find_by(id: self.user_id)

user.add_to_set(my_book_list: 'First Story')
p user.my_book_list
=> ['First Story']

user.add_to_set(my_book_list: 'Second Story')
p user.my_book_list
=> ['First Story', 'Second Story']

user.add_to_set(my_book_list: 'Third Story')
p user.my_book_list
=> ['First Story', 'Second Story', 'Third Story']

user.pull(my_book_list: 'Second Story')
p user.my_book_list
=> ['First Story', 'Third Story']

If you had duplicates in the set you can use pull_all, but you are using add to set so you won't need to.

like image 82
ABrowne Avatar answered Jul 17 '26 14:07

ABrowne



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!