Vai al contenuto principale

Come usare updateMany() in MongoDB per modificare più documenti

Scopri come usare e ottimizzare le prestazioni dell’operatore updateMany() in MongoDB per aggiornare più documenti in un’unica operazione.
· 4 min leggi

Scopri con l'IA

Quando si lavora con MongoDB, possono esserci scenari in cui vuoi aggiornare più documenti con un’unica operazione. Anche se potresti iterare i documenti e aggiornarli singolarmente, updateMany offre una soluzione più rapida ed efficiente.

In questo breve tutorial, impareremo a usare l’operatore updateMany in MongoDB e a ottimizzare le query per ottenere le migliori prestazioni possibili.

Per creare una solida base sulle funzionalità di gestione dei dati di MongoDB con Python, valuta di esplorare il corso Introduction to MongoDB in Python.

Un esempio pratico di aggiornamento di più documenti MongoDB

Per illustrare il concetto, usiamo un esempio pratico in cui potresti voler aggiornare più di un documento alla volta.

Prendiamo i seguenti dati come base per l’esempio:

[
    { "name": "Nic Raboy", "title": "Master of Shenanigans", "salary": 50000, "last_raise_date": new Date("2013-06-01") },
    { "name": "Megan Grant", "title": "Word Wrangler", "salary": 125000, "last_raise_date": new Date("2020-12-01") },
    { "name": "Tony Kim", "title": "Alliance Czar", "salary": 80000, "last_raise_date": new Date("2025-02-01") },
];

Nel JSON sopra, abbiamo tre dipendenti di un’azienda fittizia. L’azienda vuole dare a tutti un aumento della retribuzione se non hanno ricevuto adeguamenti salariali da un certo tempo.

Per aggiornare tutti coloro che rientrano nei criteri, possiamo usare l’operatore updateMany in MongoDB. Per raggiungere il nostro obiettivo, potremmo arrivare a un’istruzione come la seguente:

db.employees.updateMany(
    {
        "last_raise_date": {
            "$lte": new Date("2024-01-01")
        }
    },
    {
        "$mul": { "salary": 1.06 },
        "$set": { "last_raise_date": new Date() }
    }
);

Dunque, cosa fa l’operazione updateMany qui sopra?

Facendo un passo indietro, l’operatore updateMany accetta due parametri con un terzo opzionale. 

  • Il primo parametro è un oggetto che rappresenta i dati che vogliamo filtrare. 
  • Il secondo parametro sono le modifiche che vogliamo applicare ai risultati trovati dal filtro. 
  • Il terzo parametro opzionale può essere { “upsert”: true }, che inserirebbe un documento se non ci fossero corrispondenze.

Tenendo questo a mente, stiamo prima filtrando tutti i documenti in cui il last_raise_date è precedente a "2024-01-01". Tornando al nostro dataset molto semplice, sappiamo che due dei tre documenti corrispondono:

[
    { "name": "Nic Raboy", "title": "Master of Shenanigans", "salary": 50000, "last_raise_date": new Date("2013-06-01") },
    { "name": "Megan Grant", "title": "Word Wrangler", "salary": 125000, "last_raise_date": new Date("2020-12-01") }
];

Sui documenti filtrati verranno effettuate due modifiche in base al parametro dei criteri di modifica.

"$mul": { "salary": 1.06 },

Per prima cosa, usiamo l’operatore $mul per moltiplicare un campo per un valore. Nel nostro esempio, vogliamo dare a ogni dipendente idoneo un aumento del 6% dello stipendio. Questo significa che stiamo semplicemente moltiplicando il valore corrente del campo per 1,06.

Per aiutarci a documentare gli adeguamenti salariali e al tempo stesso prevenire aumenti accidentali in futuro, vogliamo aggiornare last_raise_date alla data corrente:

"$set": { "last_raise_date": new Date() }

Se eseguissimo di nuovo l’operazione updateMany, non accadrebbe nulla perché il last_raise_date usato nel filtro non corrisponderebbe più a nessuno dei nostri tre documenti.

Quanto sopra è solo un esempio, ma i tuoi criteri di filtro possono essere molto più complessi e, allo stesso modo, anche ciò che prevedi di modificare può essere più complesso, a seconda del caso d’uso. Puoi saperne di più su updateMany di MongoDB in questo video. 

Aumenta le prestazioni del tuo update con un indice MongoDB

Nel nostro esempio, abbiamo lavorato con tre piccoli documenti. A prescindere dall’operazione che lanciamo sulla nostra collezione, sarà veloce perché i dati sono pochi. Tuttavia, pensa a un’applicazione in produzione in cui lavori con milioni di documenti o esegui spesso l’operazione di update.

Se provassimo a usare l’operatore updateMany su milioni di documenti, potrebbe richiedere tempo a meno di avere un indice adeguato impostato per i criteri di filtro.

Per creare un indice per il nostro esempio, possiamo eseguire qualcosa del genere:

db.employees.createIndex({ "last_raise_date": 1 });

Puoi verificare che l’operazione updateMany stia usando il nostro indice eseguendo quanto segue:

db.runCommand({
    "explain": {
        "update": "employees",
        "updates": [
            {
                "q": { 
                    "last_raise_date": { 
                        "$lte": new Date("2024-01-01") 
                    }
                },
                "u": {
                    "$mul": { "salary": 1.06 },
                    "$set": { "last_raise_date": new Date() }
                }
            }
        ]
    },
    "verbosity": "allPlansExecution"
});

Nei risultati, se inputStage è "IXSCAN", allora stai usando un indice e stai massimizzando le prestazioni di updateMany. Se inputStage è "COLLSCAN", allora non stai usando un indice e potresti dover ripensare a come crearlo in base ai tuoi criteri di filtro.

Per evitare confusione, sopra stiamo usando runCommand per profilare la nostra operazione di aggiornamento di più documenti. Se non ti servono informazioni del profiler, resta sulla versione molto più semplice ed elegante di updateMany.

Conclusione

Aggiornare più documenti in un’unica operazione in MongoDB non è un compito difficile, come visto in tutto il tutorial. 

Usando l’operatore updateMany, possiamo definire dei criteri di filtro con cui confrontare i nostri documenti e poi dei criteri di modifica con un elenco di cambiamenti da applicare. Questa operazione updateMany può essere ulteriormente ottimizzata assicurandoti di avere un indice adeguato in linea con i tuoi criteri di filtro.

Se sei nuovo ai database non relazionali, il corso Introduction to NoSQL offre una panoramica utile di concetti come i document store.

FAQ

Qual è la differenza tra updateOne e updateMany in MongoDB?

 updateOne modifica il primo documento corrispondente, mentre updateMany aggiorna tutti i documenti che soddisfano i criteri di filtro. Scegli in base all’ampiezza della modifica desiderata.

Posso usare updateMany con upsert in MongoDB?

Sì, aggiungendo { upsert: true } come terzo argomento verrà inserito un nuovo documento se non vengono trovate corrispondenze. Tuttavia, è più comunemente usato con updateOne.

Quali sono alcuni casi d’uso comuni di updateMany?

Spesso si usa per aggiornamenti in batch come adeguare i prezzi, modificare gli stati degli utenti o ripulire campi obsoleti in grandi dataset.

updateMany restituisce dei risultati?

Sì, restituisce un oggetto con informazioni come matchedCount e modifiedCount, che indicano quanti documenti sono stati trovati e aggiornati.

Cosa succede se nessun documento corrisponde al filtro in updateMany?

Se non ci sono documenti corrispondenti e non si usa upsert, l’operazione termina senza modifiche. Non viene generato alcun errore.

updateMany è atomico in MongoDB?

No, non è atomica su più documenti. Ogni aggiornamento di singolo documento è atomico, ma non lo è collettivamente.

Come posso testare le prestazioni delle operazioni updateMany?

Usa i metodi explain() o runCommand({ explain: ... }) per vedere se la tua query usa un indice o esegue una scansione della collezione.

Posso concatenare più operatori di update in updateMany?

Sì, MongoDB supporta la combinazione di operatori come $set, $inc, $mul, ecc., in una singola chiamata a updateMany.

Qual è l’impatto degli indici sulle operazioni updateMany?

Gli indici possono migliorare drasticamente le prestazioni riducendo il numero di documenti scansionati durante il filtraggio.

Come annullo un’operazione updateMany eseguita per errore?

Dovresti ripristinare da un backup o dai log, poiché MongoDB non ha un rollback integrato per updateMany. Testa sempre in staging e fai il backup dei dati di produzione prima.

Nic Raboy

Autore

Nic Raboy

Nic Raboy è un Responsabile Developer Relations presso MongoDB, dove guida un team di sviluppatori Python, Java, C# e PHP che creano contenuti straordinari per aiutare gli sviluppatori a integrare con successo MongoDB nei loro progetti. Ha esperienza con Golang e JavaScript e spesso scrive delle sue molte avventure nello sviluppo.

Argomenti

Correlato