2012-03-06 10 views
5

Estoy trabajando con MongoDB en mi proyecto actual y estoy un poco confundido acerca de la forma correcta de crear soporte para modificaciones concurrentes.Preocupaciones de Atomicidad de MongoDB - Modificar un documento en la memoria

Tengo una matriz de objetos. Cuando entra una solicitud, quiero inspeccionar el último elemento de esa matriz y tomar una decisión condicional sobre cómo responder. Mi código es algo como lo siguiente:

# 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) 

estoy preocupado por la situación en la que:

  1. En el manejo de petición A, encuentro la last_element_id es válida, y la respuesta se debe anexar hasta el final de la lista.
  2. Antes de completar las operaciones de agregar() y guardar(), otra solicitud, B, es manejada.
  3. B también ve que last_element_id es válido, agrega() la respuesta y guarda().
  4. Ahora, la respuesta de A se pone en cola al final de la matriz, pero la respuesta ya no sigue al supuesto 'last_element_id' ya que la respuesta de B se coló de antemano.

¿Cuál es la forma correcta de manejar este tipo de lógica en el modelo de atomicidad de Mongo? No quiero emplear bloqueos si puedo evitarlos, ya que la aplicación WSGI se puede ejecutar en múltiples procesos simultáneamente.

Gracias!

Respuesta

1

Puede usar el bloqueo optimista .. ,, una forma es agregar un campo denominado versión al documento y luego incrementarlo en cada actualización, y cuando actualice asegúrese de que la versión en el documento sea la misma que uno que se lee en.

pudiera dar más detalles, pero esto está bastante bien documentado en http://www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-%22UpdateifCurrent%22

Quiero saber si esto funciona para usted,

+0

¡Parece que esto puede funcionar para lo que estoy haciendo! ¡Gracias! Informará de nuevo. –

+0

Perfecto. ¡Gracias! –

+0

@Shekar, simplemente puede lograr esto con findandmodify (este caso). verifique mi respuesta para más información – RameshVel

1

usted puede utilizar findAndModify a atomicallay manejar la transacción (al menos este caso).

Este comando acepta upsert marca, que puede utilizar para actualizar o insertar el documento basado en su existence. Compruebe el siguiente ejemplo

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

y la emisión de este comando con la consulta _id:1 empujará (append) nuevo elemento al arr

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

y esto creará uno nuevo porque el _id:2 no existe ya

> 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 ] } 

Espero que ayude.

+0

¿El soporte de las consultas en findAndModify es lo suficientemente rico para lo que estoy tratando de lograr?Solo quiero insertar el nuevo elemento en la parte posterior de la matriz si el último elemento de la matriz es algún valor conocido. Este valor conocido se envía como un parámetro en la solicitud POST. –

+0

Sí, podrías hacer eso con findAndModify. Es una elección perfecta. En mis ejemplos anteriores, puede sustituir fácilmente su consulta y pulsar para que funcione. – RameshVel

Cuestiones relacionadas