> Approfondire un argomento tra questi studiando il capitolo 8 (Indexing e query optimization) o 9 (Text search) del libro “MongoDB in action” disponibile sul sito dell’insegnamento.
>
> Riassumere quindi alcune delle tecniche imparate e mostrarne un'applicazione pratica su alcune nuove interrogazioni sul dataset Amazon utilizzato nelle esercitazioni.
>
> (es. decidere gli indici adeguati ottimizzandone l’esecuzione o mostrare l’utilizzo di varie tecniche di text search, commentando le scelte effettuate).
L'attività è stata svolta su MongoDB 6.0.2, attraverso la macchina virtuale predisposta su [Azure Labs](https://labs.azure.com/virtualmachines), `LabBDA2`.
Sviluppando una applicazione o effettuando analisi su dati, è possibile aver bisogno di effettuare query sul database relative ai contenuti di esso in linguaggio naturale.
Per comodità, MongoDB include funzionalità basilari per la ricerca in linguaggio naturale, in modo che i suoi utilizzatori possano usufruirne senza dover configurare un motore di ricerca esterno come [ElasticSearch](https://www.elastic.co/).
Esistono [funzionalità di ricerca più avanzate](https://www.mongodb.com/docs/atlas/atlas-search/atlas-search-overview/) basate su [Apache Lucene](https://lucene.apache.org/), ma sono limitate al piano managed (a pagamento) del database, [MongoDB Atlas](https://www.mongodb.com/pricing): esse non saranno trattate in questa relazione.
Quando si effettua una query in linguaggio naturale su una collezione di documenti, l'obiettivo è quello di trovare uno o più documenti dal contenuto più simile possibile al contenuto della richiesta effettuata: ad esempio, in un database di film, si potrebbe voler trovare un film con uno specifico titolo, o in cui compare un termine specifico nella descrizione.
Non effettuando confronti diretti (`"a" === "b"`) tra i contenuti dei campi interrogati e i termini della query, non è possibile effettuare una ricerca binaria sugli indici della collezione; è invece necessario utilizzare un indice apposito creato preventivamente detto *[Text Index](https://www.mongodb.com/docs/manual/core/index-text/)*, in grado di indicizzare correttamente le singole parole dei documenti nella collezione.
Per creare un Text Index, è necessario invocare il metodo `.createIndex()` della collezione con un oggetto dove tutti le chiavi dei campi che si vogliono indicizzare sono mappate alla stringa `"text"`.
Ogni collezione può avere associato **un solo Text Index**, che può però coprire qualsiasi numero di suoi campi di testo.
Per indici multi-campo, è consigliabile specificare nelle opzioni di `.createIndex()` un nome attraverso il campo `name`, onde evitare il comportamento predefinito di MongoDB di concatenare i nomi dei campi che l'indice contiene:
```javascript
// Creazione di un Text Index con nome personalizzato
Per dare più priorità ad certi campi rispetto ad altri nella ricerca, attraverso l'opzione `weights` di `.createIndex()` è possibile specificare il peso di ciascun campo:
```javascript
// Creazione di un Text Index con nome e pesi personalizzato
Per operare efficacemente con il linguaggio naturale, è necessario effettuare alcune operazioni di preprocessing sulle stringhe in questione, trasformandole in insiemi di token.
Una volta creato l'indice, è possibile usarlo per effettuare interrogazioni di linguaggio naturale sulla collezione utilizzando i metodi della collezione `.find()` e le chiavi speciali `$text` e `$search`:
```javascript
// Cerca documenti che contengono le parole della stringa "La Mia Query" nei campi indicizzati
Circondando di virgolette doppie `"` un termine della ricerca, è possibile richiedere la presenza sicura di uno dato termine o frase all'interno del documento:
// Cerca documenti che contengono le parole della stringa "La Mia Query" nei campi indicizzati, e che hanno sicuramente la parola "Mia" da qualche parte
Al fine di ordinare i documenti restituiti dalla query `$text`, a ciascuno di essi viene assegnato un punteggio, che dipende quanto ogni token di esso è rilevante alla richiesta effettuata, e, se specificati, dai pesi dell'indice interrogato.
È possibile includere il punteggio nel contenuto dei documenti restituiti specificando l'oggetto `{$meta: "textScore"}` come valore di una delle chiavi di proiezione del metodo `.find()`.
```javascript
// Cerca documenti che contengano le parole della stringa "Tutto su MongoDB"
### 0 - Creazione del Text Index sulla collezione `reviews`
La collezione `reviews` ha due campi di testo in linguaggio naturale: `summary`, il titolo della recensione, e `reviewText`, il contenuto completo della recensione.
Quindi, si è eliminato l'indice pre-esistente `summary_text`, e si è creato un indice contenente quei due campi, dando peso maggiore al campo `summary`, più rilevante.
Si desidera cercare all'interno della collezione tutti i dati relativi al videogioco _[Terraria](https://store.steampowered.com/app/105600/Terraria/)_.
La query ha successo e restituisce un documento con le caratteristiche richieste, ma il dataset pare essere sporco: immagine e prezzo del prodotto si riferiscono a una copia del videogioco _[Minecraft](https://www.minecraft.net/en-us)_.
description: "Dig, fight, explore, build! Nothing is impossible in this action-packed adventure game. The world is your canvas and the ground itself is your paint. Grab your tools and go! You can do many things in Terraria: make weapons and fight off a variety of enemies in numerous biomes, dig deep underground to find accessories, money, and other useful things, gather wood, stone, ores, and other resources to create everything you need to make the world your own and defend it. Build a house, a fort, even a castle and people will move in to live there and perhaps even sell you different wares to assist you on your journey. But beware, there are even more challenges awaiting you. Are you up to the task? ? ??? Terraria: Collector's Edition Includes: ??? In game item ??? Trading cards ??? Poster ??? Product Features: ??? Sandbox play ??? Randomly generated worlds ??? Free content updates ??? Co-op and PvP multiplayer modes playable via internet ? System Requirements OS: Windows Xp, Vista, 7. Processor: 1.6 Ghz. Memory: 512MB. Hard Disk Space: 200MB. Video Card: 128mb Video Memory, capable of Shader Model 1.1. DirectX?: 9.0c or Greater.",
Si desidera trovare tutte le recensioni negative (2 stelle o inferiore) relative a qualche tipo di gioco (contenenti la parola "game" in qualche campo).
// Trova i videogiochi che contengono il termine "Dante"
{$match: {
$text: {$search: "Dante"},
// Le categorie sono tuple di termini dal più generale al più specifico; per risolvere questa query è sufficiente che un termine qualsiasi sia "Video Games"
Si desidera trovare una bizzarra irregolarità statistica: trovare i dati dei 10 prodotti con le recensioni più alte, contando solo le recensioni in cui compare la parola "cringe".
Si effettua la seguente query:
```javascript
db.reviews.aggregate([
// Trova le recensioni che contengono il termine "cringe"
{$match:
{$text: {$search: "cringe"}},
},
// Raggruppa le recensioni per codice prodotto, conteggiandole e calcolandone la valutazione media
// Ordina i prodotti per valutazione media decrescente, poi per numero di recensioni decrescente, e infine per ordine lessicale di ASIN, in modo da avere risultati deterministici