sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB - $establecido para actualizar o empujar el elemento Array

En realidad, hacer lo que parece que dices que estás haciendo no es una operación única, pero explicaré las partes necesarias para hacer esto o cubriré otras situaciones posibles.

Lo que está buscando es en parte el $ posicional operador. Necesita parte de su consulta para "encontrar" también el elemento de la matriz que desea.

db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

Entonces el $ representa la posición coincidente en la matriz, por lo que la parte de actualización sabe qué elemento de la matriz actualizar. Puede acceder a campos individuales del documento en la matriz o simplemente especificar el documento completo para actualizar en esa posición.

db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

Si los campos de hecho no cambian y solo desea insertar un nuevo elemento de matriz si no existe exactamente el mismo, entonces puede usar $addToSet

db.products.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        $addToSet:{ 
            "recentviews": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    }
)

Sin embargo, si solo está buscando "empujar" a una matriz mediante un valor de clave singular si eso no existe, entonces debe realizar un manejo manual más, primero viendo si el elemento en la matriz existe y luego haciendo $push declaración donde no lo hace.

Obtiene algo de ayuda de los métodos mongoose al hacer esto rastreando la cantidad de documentos afectados por la actualización:

Product.update(
    { 
        "_id": ObjectId("536c55bf9c8fb24c21000095"),
        "recentviews.viewedby": "abc"
    },
    { 
        "$set": { 
            "recentviews.$": {
                 "viewedby": "abc",
                 "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
        }
    },
    function(err,numAffected) {

        if (numAffected == 0) {
            // Document not updated so you can push onto the array
            Product.update(
                { 
                    "_id": ObjectId("536c55bf9c8fb24c21000095")
                },
                { 
                    "$push": { 
                        "recentviews": {
                            "viewedby": "abc",
                            "vieweddate": ISODate("2014-05-09T04:12:47.907Z")
                        }
                    }
                },
                function(err,numAffected) {

                }
            );
        }            

    }
);

La única palabra de precaución aquí es que hay un pequeño cambio de implementación en los mensajes writeConcern de MongoDB 2.6 a versiones anteriores. No estoy seguro en este momento de cómo la API de mangosta realmente implementa el retorno de numAffected argumento en la devolución de llamada, la diferencia podría significar algo.

En versiones anteriores, incluso si los datos que enviaste en la actualización inicial coincidían exactamente con un elemento existente y no se requería un cambio real, la cantidad "modificada" se devolvería como 1 aunque no se actualizó nada.

Desde MongoDB 2.6, la respuesta de preocupación de escritura contiene dos partes. Una parte muestra el documento modificado y la otra muestra la coincidencia. Entonces, mientras que la parte de la consulta devolvería la coincidencia que coincide con un elemento existente, el recuento real de documentos modificados devolvería como 0 si de hecho no se requiere ningún cambio.

Entonces, dependiendo de cómo se implemente realmente el número de retorno en mongoose, en realidad podría ser más seguro usar el $addToSet operador en esa actualización interna para asegurarse de que si el motivo de los documentos afectados por cero no era solo que el elemento exacto ya existía.