Come interrogare MongoDB con il metodo find e il NoSQL

Il metodo find di MongoDB permette di estrarre i documenti di una collezione che rispettano particolari condizioni. In questo articolo vi farò vedere come interrogare un Database MongoDB e scrivere delle query con il linguaggio NoSQL della MongoShell.

Esempi di utilizzo del metodo find

Iniziamo lanciando sulla MongoShell una query come la seguente:

db.fatture.find();

Vedremo in output 20 documenti della collezione fatture del database corrente, come nell’immagine in basso

esempio output find di MongoDB

Come suggerito dall’immagine, lanciando il comando it possiamo visualizzare altri 20 documenti e iterare questo procedimento fino alla fine. Se volessi visualizzare direttamente l’intero output, potrei applicare il metodo toArray(), ma facciamo attenzione nel caso di collezioni molto numerose!

db.fatture.find().toArray();

I documenti in ouput saranno separati da una virgola e racchiusi nel loro complesso da delle parentesi quadre, formando così un array di documenti.

Filtrare i documenti con il metodo find

Vediamo ora come estrarre soltanto i documenti che rispettano particolari condizioni. Partiamo con un esercizio molto semplice: supponiamo di avere una collezione di nome clienti e di voler visualizzare tutti i documenti dove la chiave nome è uguale a Nicola. Scriveremo

db.clienti.find({"nome":{"$eq":"Nicola"}});

Facciamo alcune osservazioni:

  • anche in questo caso vedremo i risultati a gruppi di venti documenti alla volta;
  • l’operatore $eq potrebbe essere omesso per usare la sintassi più leggera db.clienti.find({“nome”:”Nicola”});
  • ogni elemento della query è case sensitive. Ad esempio nel codice in alto stiamo interrogando la collezioni clienti, non la Clienti o la CLIENTI. Teniamo presente inoltre che non avremo mai un errore del tipo “la collezione non esiste“, ma semplicemente la query non restituirà alcun risultato. Anche il valore della chiave cercato sarà case sensitive (nell’esempio in alto “Nicola”).

Analogamente all’operatore $eq, potremmo utilizzare altri metodi di confronto come in questa tabella:

OperatoreSignificato
$gtmaggiore
$gtemaggiore o uguale
$ltminore
$lteminore o uguale
$nediverso
$inin elenco
$regexespressioni regolari

Vediamo ad esempio che con l’operatore $in possiamo scrivere una query per estrarre i clienti residenti in Lombardia, Puglia e Molise (dove tali valori sono salvati nel Database esattamente con la sola iniziale maiuscola).

db.clienti.find({"regione_residenza":{
                     "$in":["Lombardia",
                            "Puglia",
                            "Molise"]
                                      }
                 });

Metodo find con chiavi di tipo Array e sottodocumenti

I documenti di MongoDB possono contenere anche chiavi multi-valore, rappresentate da insiemi di valori separati da una virgola e racchiusi tra parentesi quadre. In questo caso l’operatore $eq ha un significato diverso: verranno restituiti i documenti dove almeno uno dei valori nell’array è uguale a quello indicato. Ad esempio la query:

db.squadre.find({"trofei":{"$eq":"Campionato"}});

estrae le squadre dove all’interno della chiave trofei di tipo array è presente almeno una volta il valore “Campionato“. Per gli array posso utilizzare anche gli operatori $in e $all. In questo modo estraiamo i documenti che contengono almeno uno dei valori indicati dopo $in, oppure tutti i valori dopo $all. Ad esempio la query

db.squadre.find({"trofei":{"$all":["Campionato",
                                   "Coppa Italia"]
                          }
                 });

mostra le squadre per il cui l’array di trofei contiene sia Campionato e sia Coppa Italia, a prescindere dall’ordine e dal numero di occorrenze.

Nel caso in cui una chiave abbia come valore un sotto-documento (detto anche array associativo), allora individuerò le sotto-chiavi tramite la sintassi chiave.sottochiave, ad esempio:

db.clienti.find({"indirizzo.citta":"Milano"});

Scrivere condizioni con AND e OR su MongoDB

Per combinare più condizioni con gli operatori logici and e or dovrò inserire le varie condizioni in un array. Quest’ultimo sarà il valore associato alla chiave $and o $or del metodo find(). Vediamo un esempio:

db.clienti.find({
    $and:["nome":"Nicola",
          "cognome":"Iantomasi"]
                 });

Con la query precedente estraiamo i documenti che rispettano tutte le condizioni esplicitate. In modo analogo potrei scrivere una query con l’or, oppure annidare più $and e $or in un’unica query.

Il codice precedente può essere riscritto in questo modo, utilizzando $and in maniera implicita:

db.clienti.find({
   "nome":"Nicola",
   "cognome":"Iantomasi"
                 });

Dobbiamo fare molta attenzione però perché non sempre le due sintassi sono equivalenti. In particolare, con l’and implicito non dobbiamo mai ripetere la stessa chiave più di una volta, perché verrebbe presa in considerazione una sola delle due condizioni. Ad esempio la query

db.fatture.find({
   "importo":{$gte:100},
   "importo":{$lte:200}
   })

non estrae le fatture con importo compreso tra 100 e 200 in quanto: essendo la chiave importo ripetuta più volte in un singolo documento, verrà considerata soltanto una delle due specifiche (tendenzialmente l’ultima). Per scrivere la query correttamente occorre usare $and

db.fatture.find({
   $and:[{"importo":{$gte:100}},
         {"importo":{$lte:200}}]
   });

o, se proprio vogliamo utilizzare l’and implicita, possiamo scrivere

db.fatture.find({
   "importo":{$gte:100,
              $lte:200}     
   });

Attenzione ai tipi!

L’output del find dipende anche dai tipi associati alle chiavi nei documenti. Ad esempio, se la chiave data_fattura è sempre di tipo date, allora occorre specificare tale informazioni anche per i valori utilizzati nella find, ricorrendo all’istruzione ISODate. Ad esempio scriverò

db.fatture.find({
   "data_fattura":{$gte:ISODate("2022-01-01")}
                 });

per estrarre tutte le fatture con data successiva o uguale al primo gennaio 2022. Vi ricordo inoltre che le chiavi date su MongoDB incorporano anche le informazioni sull’ora. Se non specificata, verrà considerato di default le 00:00:00. Uno dei modi corretti per estrarre tutte le fatture del primo gennaio 2022 può essere dunque:

db.fatture.find({
   $and:[{"data_fattura":{$gte:ISODate("2022-01-01")}},
         {"data_fattura":{$lt:ISODate("2022-01-02")}}
        ]});

Visualizzare soltanto alcune chiavi

Il metodo find accetta in input un secondo documento dopo quello per specificare il filtro. Con esso possiamo indicare quali chiavi visualizzare, specificando un 1 dopo il nome della chiave. Riprendendo la prima query di questo articolo, possiamo espanderla così:

db.clienti.find({"nome":{"$eq":"Nicola"}}, 
                {"nome":1,
                 "cognome":1});

per visualizzare in output soltanto le chiavi nome, cognome e _id. Quest’ultima infatti sarà sempre visibile, almeno che non specifichiamo espressamente “_id”:0.

Continua a imparare

In questo articoli abbiamo visto vari modi di utilizzare il metodo find per scrivere query NoSQL e interrogare le collezioni di un database non relazionale di MongoDB. Una volta compresa la sintassi json-oriented occorre fare molta attenzione ai tipi delle chiavi, a utillizzare correttamente gli operatori $and e $or, oltre a gestire anche i casi più complessi con array e sotto-documenti.

Torna in alto
Torna su