Supongamos que tengo un documento

{
  maxCountAllowed:100,
  currentCount:99
}

Y tengo una API que los usuarios llaman para incrementar el CurrentCount si aún no es 100 ...

if(document.currentCount < document.maxCountAllowed){
    document.currentCount ++;
    document.save();
}else{
    console.log("sorry maximum count reached");
}

Suponga que 2 o más usuarios llamaron a la API al mismo tiempo ... ambos encontrarán que currentCount sigue siendo 99, por lo que la función continuará y ambos incrementarán el currentCount para ser 101 o más ... ¿cómo puedo evitar algo como esto? Incluso si ambos lo hacen 100, todavía quiero que solo uno de ellos pueda actualizarse y el otro reciba el mensaje de error.

0
You Ma 27 oct. 2017 a las 20:52

3 respuestas

La mejor respuesta

Mongo proporciona atomicidad a nivel de documento como se describe aquí: https: // docs.mongodb.com/v3.4/tutorial/update-documents/#behavior Esto significa que si hay dos operaciones de actualización concurrentes en un objeto, se ejecutarán consecutivamente.

Además, las operaciones de actualización admiten el operador $ inc: https: // docs .mongodb.com / manual / reference / operator / update / inc / # up._S_inc

Y la última parte es $ where operador: https: // docs. mongodb.com/manual/reference/operator/query/where/#examples Tenga en cuenta que no es tan eficaz como consultar con constantes.

Para que pueda actualizar solo los documentos conformes:

db.products.update(
  { $where : "this.currentCount < this.maxCountAllowed" },
  { $inc: { currentCount: 1 } }
);

Luego verifique el resultado de la operación para averiguar si se actualizó algo.

3
marc_s 7 nov. 2017 a las 21:27

Puede realizar esta operación en la base de datos como una actualización con una condición de consulta adicional. En primer lugar, debe buscar su documento para conocer el límite. Entonces supongamos que el _id de su documento es igual a 1, por lo que puede ejecutar dicha actualización:

db.yourCollection.update({_id: 1, currentCount: {$lt: 100}}, { $inc: { currentCount: 1 } });

$ inc realizará el incremento, pero solo si el estado actual del documento tiene un campo currentCount con un valor inferior a 100, que es su límite definido en otro campo de este documento.

1
mickl 27 oct. 2017 a las 18:03

Creo que el caso del que estás hablando nunca puede suceder. Imagine que habrá 2 solicitudes al mismo tiempo, ambas obtendrán 99/100 como resultado. Luego, ambos intentarán actualizar a 100/100. Está incrementando el valor que obtiene de la base de datos en el script de nodo, no el valor en mongo directamente.

También podría usar db.collection.findAndModify, pero parece que no hay una API de mangosta para esto.

https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/

1
Martin Adámek 27 oct. 2017 a las 18:04