2011-01-17 11 views
7

sto cercando di fare qualcosa di piuttosto semplice credo:Mongoide - Gestione array? inserire un valore univoco, rimuovere il valore se esiste?

1) Inserire un valore in un campo di matrice solo se tale valore non è già presente

2) rimuovere un valore se esiste nella matrice

ho appena idea di come fare nessuna di queste cose ... per il momento io sono solo inserire la mia valore senza controllare se esiste già: myArray < < obj.id

Grazie,

Alex

ps: usando Rails 3.0.3, 1.1.5 e mongo mongoid 2.0.0.rc5

ps2: questa è la sintassi MongoDB per ottenere ciò che voglio, ma non ho idea di come farlo in mongoid

{ $addToSet : { field : value } } 

valore aggiunge alla matrice solo se non nella matrice già, se il campo è un array esistente, altrimenti imposta campo per il valore della matrice se il campo non è presente. Se il campo è presente ma non è una matrice, viene generata una condizione di errore.

di aggiungere molte valuest.update

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

{ $pop : { field : 1 } } 

rimuove l'ultimo elemento di un array (aggiunta nel 1,1)

{ $pop : { field : -1 } } 

rimuove il primo elemento di un array (aggiunta nel 1.1) |

+0

I don' so la sintassi con il driver mongo rotaie, nut $ addToSet è quello che vuoi. –

+0

sì, lo so .. :(ma non ho idea di come implementarlo – Alex

risposta

8

Secondo Chris Hawk da Mongoid googlegroup:

Array nei documenti Mongoid sono semplici array Ruby. Vedere la documentazione per la classe Array: http://www.ruby-doc.org/core/classes/Array.html

Così, per l'inserimento si può semplicemente fare:

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

E per la rimozione:

array.delete(object) 
+2

Non c'è il rischio di condizioni di gara? Penso che sia meglio usare un atomico $ addToSet – vdaubry

0

degni di nota, in mongoid, come di 2.0 .0pre4 Non vedo alcun supporto addToSet. mongo_mapper (while imo less maintained :() supporta questo metodo tramite push_uniq.

a meno che, in mongolo, se si sta lavorando direttamente con il metodo di relazione, non è necessario eseguire l'inclusione? lavorando direttamente con l'array, lo fai.

Esempio:

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

Si desidera utilizzare il metodo add_to_set, come documentato (un po ') qui: http://mongoid.org/en/mongoid/docs/persistence.html#atomic

Esempio:

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

si può dare un valore singolo o anche una serie di valori. Quest'ultimo utilizzerà il qualificatore $each di mongo insieme a $addToSet quando si aggiunge ogni elemento dell'array al campo specificato.

+0

La risposta originale ha fornito un collegamento obsoleto ai documenti v2 ma è stato aggiornato (grazie a @Selva!). Se stai ancora usando Mongoid 2, ecco un link ai documenti 'add_to_set' per quella versione: http://two.mongoid.org/docs/persistence/atomic. html # add_to_set – xentek

0

È possibile utilizzare pull operator, che è atomico, per rimuovere un singolo elemento. Ecco un esempio, dove l è un riferimento ad un documento con un campo di matrice array:

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

calcolata può essere fatto con add_to_set, come menzionato in precedenza:

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.

Problemi correlati