2012-03-06 13 views
5

sto lavorando con MongoDB sul mio progetto in corso e un po 'confuso circa il modo corretto per costruire un sostegno per le modifiche simultanee.MongoDB atomicità Le preoccupazioni - Modifica di un documento in memoria

Ho un array di oggetti. Quando arriva una richiesta, voglio ispezionare l'ultimo elemento di quell'array e prendere una decisione condizionale su come rispondere. Il mio codice simile a quanto segue:

# Find the last object ID in the array. 
last_element_id = str(document['objects'][-1]) 
if last_element_id != the_element_id_the_request_is_responding_to: 
    db.documents.insert({ 
     ... 
    }) 
else: 
    # Append the response to the end of the array. 
    document['objects'].append(new_element_id) 
    db.documents.save(document) 

Sono preoccupato per la situazione in cui:

  1. Nella gestione richiesta Un, trovo il last_element_id è valida, e la risposta dovrebbe essere aggiunto alla fine della lista. operazioni
  2. Prima l'append() e salvare() completa, un'altra richiesta, B, è gestito.
  3. B vede anche l'last_element_id è valido, aggiunge() la risposta e salva().
  4. Ora, la risposta di A è accodata alla fine dell'array, ma la risposta non segue più il supposto 'last_element_id' poiché la risposta di B si è bloccata in anticipo.

Qual è il modo corretto di gestire questo tipo di logica nel modello atomico di Mongo? Non voglio utilizzare i blocchi se posso evitarli, poiché l'applicazione WSGI può essere eseguita in più processi contemporaneamente.

Grazie!

risposta

1

È possibile utilizzare il blocco ottimistico .., un modo è quello di aggiungere un campo chiamato versione al documento e quindi incrementarlo ad ogni aggiornamento, e quando si aggiorna assicurarsi che la versione nel documento sia la stessa del quello che si leggono in.

ho potuto dare maggiori dettagli, ma questo è abbastanza ben documentato a http://www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-%22UpdateifCurrent%22

Fatemi sapere se questo funziona per voi,

+0

Sembra che questo possa funzionare per quello che sto facendo! Grazie! Riferirò. –

+0

Perfetto. Grazie! –

+0

@Shekar, puoi semplicemente raggiungerlo con findandmodify (questo caso). controlla la mia risposta per maggiori informazioni – RameshVel

1

È possibile utilizzare findAndModify per atomicallay gestire l'operazione (almeno questo caso).

Questo comando accetta il flag upsert, che è possibile utilizzare per aggiornare o inserire il documento in base al suo existence. Controllare l'esempio di seguito

> db.upsertTest.find() 
{ "_id" : 1, "arr" : [ 1 ] } 

e l'emissione di questo comando con la query _id:1 spingerà (accodare) nuovo elemento arr

> db.upsertTest.findAndModify({query: {_id:1},update:{$push:{arr:2}},upsert:true,"new":true}) 
{ "_id" : 1, "arr" : [ 1, 2 ] } 

e questo creerà uno nuovo, perché il _id:2 non esiste già

> db.upsertTest.findAndModify({query: {_id:2},update:{$push:{arr:2}},upsert:true,"new":true}) 
{ "_id" : 2, "arr" : [ 2 ] } 

> db.upsertTest.find() 
{ "_id" : 1, "arr" : [ 1, 2 ] } 
{ "_id" : 2, "arr" : [ 2 ] } 

Spero che sia d'aiuto.

+0

Il supporto per le query in findAndModify è sufficientemente ricco per quello che sto cercando di ottenere?Voglio solo spingere il nuovo elemento sul retro dell'array se l'ultimo elemento dell'array è un valore noto. Questo valore noto viene inviato come parametro nella richiesta POST. –

+0

Sì, si potrebbe farlo con findAndModify. È una scelta perfetta. Nei miei esempi sopra puoi facilmente sostituire la tua richiesta e spingere per farlo funzionare .. – RameshVel

Problemi correlati