简体   繁体   中英

Mongoid - Array management ? insert unique value, remove value if exists?

I am trying to do something rather simple I believe:

1) insert a value in an array field only if that value is not already present

2) remove a value if it exists in the array

I have just no idea how to do any of this things... for the moment I am just inserting my value without checking if it exists already: myArray << obj.id

Thanks,

Alex

ps: using Rails 3.0.3, mongo 1.1.5 and mongoid 2.0.0.rc5

ps2: this is the mongodb syntax to achieve what I want, but I have no idea how to do this in mongoid

{ $addToSet : { field : value } }

Adds value to the array only if its not in the array already, if field is an existing array, otherwise sets field to the array value if field is not present. If field is present but is not an array, an error condition is raised.

To add many valuest.update

{ $addToSet : { a : { $each : [ 3 , 5 , 6 ] } } }
$pop

{ $pop : { field : 1  } }

removes the last element in an array (ADDED in 1.1)

{ $pop : { field : -1  } }

removes the first element in an array (ADDED in 1.1) |

You want to use the add_to_set method, as documented (somewhat) here: http://mongoid.org/en/mongoid/docs/persistence.html#atomic

Example:

model = Model.new
model.add_to_set(:field, value)
model.save

You can give it a single value or even an array of values. The latter will use mongo's $each qualifier along with $addToSet when adding each element of your array to the field you specify.

As per Chris Hawk from Mongoid googlegroup:

Arrays in Mongoid documents are simple Ruby arrays. See the docs for the Array class: http://www.ruby-doc.org/core/classes/Array.html

So, for insertion you can simply do:

array << object unless array.include?(object) 

And for removal:

array.delete(object) 

worth mentioning, in mongoid, as of 2.0.0pre4 I do not see any addToSet support. mongo_mapper (while imo less maintained :( ) supports this via push_uniq method.

short of that, in mongoid, if you are working with the relationship method directly, you don't need to do the include?. if you are working with the array directly, you do.

Example:

class Person
   include Mongoid::Document
   has_and_belongs_to_many :pets ## or has_many :pets, :stored_as => :array if your not using the latest mongoid 
end

#when using .pets no need to check, mongoid checks for you to ensure you can only add the same pet once.
pet = Pet.find("294x29s9a9292")
p = Person.find("42192189a92191a")
p.pets << pet

#when using pet_ids, you do need to check:
pet = Pet.find("294x29s9a9292")
p = Person.find("42192189a92191a")
p.pet_ids << pet.id unless p.pet_ids.include? pet.id

You can use the pull operator , which is atomic, to remove a single element. Here's an example, where l is a reference to a document with an array field array :

l.array = [1, 2, 3]
l.save
l.pull(array: 1) # atomically removes 1, leaving [2, 3]

Adding can be done with add_to_set , as previously mentioned:

l.array = [2, 3]
l.save
l.add_to_set(array: 1) # atomically adds 1, resulting in [2, 3, 1]

Here's a link to the current Mongoid documentation on Atomic operators.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM