2011-01-17 11 views
7

estoy tratando de hacer algo bastante simple que creo:Mongoid - ¿Gestión de matrices? inserte un valor único, elimine el valor si existe?

1) insertar un valor en un campo de matriz sólo si dicho valor no está ya presente

2) eliminar un valor si existe en la matriz

Acabo ni idea de cómo hacer cualquiera de estas cosas ... por el momento sólo estoy insertando el valor de mi sin comprobar si ya existe: miMatriz < < obj.id

Gracias,

Alex

ps: el uso de rieles 3.0.3, 1.1.5 y mongo MongoId 2.0.0.rc5

PS2: Esta es la sintaxis mongodb para conseguir lo que quiero, pero no tengo ni idea de cómo hacer esto en MongoId

{ $addToSet : { field : value } } 

valor se suma a la matriz sólo si su no en la matriz ya, si el campo es una matriz existente, de lo contrario conjuntos de campos para el valor de la matriz si el campo no está presente. Si el campo está presente pero no es una matriz, se genera una condición de error.

agregar muchos valuest.update

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

{ $pop : { field : 1 } } 

elimina el último elemento de una matriz (añadido en 1,1)

{ $pop : { field : -1 } } 

elimina el primer elemento de una matriz (añadido en 1.1) |

+0

I don' Conozca la sintaxis con el controlador carriles mongo, nut $ addToSet es lo que desea. –

+0

Sí, lo sé ... :(pero no tengo idea de cómo implementarlo – Alex

Respuesta

8

Según Chris Hawk de Mongoid googlegroup:

matrices en los documentos MongoId son simples matrices de Ruby. Consulte la documentación de la clase Array: http://www.ruby-doc.org/core/classes/Array.html

Por lo tanto, para la inserción puede simplemente hacer:

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

Y para la eliminación:

array.delete(object) 
+2

¿No existe el riesgo de una condición de carrera? Creo que es mejor usar un atomic $ addToSet – vdaubry

0

vale la pena mencionar, en MongoId, a partir de 2,0 .0pre4 No veo ningún soporte addToSet. mongo_mapper (while imo less mantenida :() admite esto a través del método push_uniq.

corto de eso, en mongoid, si trabajas directamente con el método de relación, no necesitas hacer el include ?. si eres trabajando con la matriz directamente, lo haces.

Ejemplo:

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 
10

Usted desea utilizar el método add_to_set, tal como se documenta (un poco) aquí: http://mongoid.org/en/mongoid/docs/persistence.html#atomic

Ejemplo:

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

Se le puede dar un único valor o incluso una matriz de valores. Este último usará el calificador $each de mongo junto con $addToSet al agregar cada elemento de su matriz al campo que especifique.

+0

La respuesta original proporcionó un enlace desactualizado a los documentos v2 pero se ha actualizado (gracias @Selva!). Si todavía está utilizando Mongoid 2, aquí hay un enlace a los documentos 'add_to_set' para esa versión: http://two.mongoid.org/docs/persistence/atomic. html # add_to_set – xentek

0

Puede usar el pull operator, que es atómico, para eliminar un solo elemento. Aquí está un ejemplo, donde l es una referencia a un documento con un campo de matriz array:

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

Adición se puede hacer con add_to_set, como se ha mencionado anteriormente:

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.

Cuestiones relacionadas