MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB - $ impostato per aggiornare o eseguire il push dell'elemento Array

In realtà fare ciò che sembra che dici di fare non è un'operazione singolare, ma illustrerò le parti necessarie per farlo o altrimenti coprire altre possibili situazioni.

Quello che stai cercando è in parte il $ posizionale operatore. Hai bisogno di parte della tua query anche per "trovare" l'elemento dell'array che desideri.

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

Quindi il $ sta per la posizione corrispondente nell'array in modo che la parte di aggiornamento sappia quale elemento nell'array aggiornare. Puoi accedere ai singoli campi del documento nell'array o semplicemente specificare l'intero documento da aggiornare in quella posizione.

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

Se i campi infatti non cambiano e vuoi solo inserire un nuovo elemento dell'array se lo stesso identico non esiste, allora puoi usare $addToSet

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

Tuttavia, se stai solo cercando "spingere" un array con un valore chiave singolare se questo non esiste, devi eseguire un po' di gestione manuale in più, vedendo prima se l'elemento nell'array esiste e quindi facendo il $push dichiarazione dove non lo fa.

Ottieni aiuto dai metodi mangusta nel farlo monitorando il numero di documenti interessati dall'aggiornamento:

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

                }
            );
        }            

    }
);

L'unico avvertimento qui è che c'è un piccolo cambiamento nell'implementazione nei messaggi writeConcern da MongoDB 2.6 alle versioni precedenti. Non essere sicuro in questo momento su come l'API mongoose implementi effettivamente il ritorno di numAffected argomento nel callback la differenza potrebbe significare qualcosa.

Nelle versioni precedenti, anche se i dati inviati nell'aggiornamento iniziale corrispondevano esattamente a un elemento esistente e non era richiesta alcuna modifica reale, l'importo "modificato" veniva restituito come 1 anche se nulla è stato effettivamente aggiornato.

Da MongoDB 2.6 la risposta al problema di scrittura contiene due parti. Una parte mostra il documento modificato e l'altra mostra la corrispondenza. Quindi, mentre la corrispondenza verrebbe restituita dalla parte della query che corrisponde a un elemento esistente, il conteggio effettivo del documento modificato verrebbe restituito come 0 se in effetti non era richiesta alcuna modifica.

Quindi, a seconda di come il numero di ritorno viene effettivamente implementato in mangusta, potrebbe essere effettivamente più sicuro utilizzare il $addToSet operatore su quell'aggiornamento interno per assicurarsi che se il motivo dello zero documenti interessati non fosse solo che l'elemento esatto esistesse già.