Differences

This shows you the differences between two versions of the page.

Link to this comparison view

bd2:laboratoare:12 [2019/12/07 13:35]
ciprian.truica
— (current)
Line 1: Line 1:
-====== Laboratorul 12 - MongoDB II ====== 
  
-===== Obiective ===== 
- 
-  * Indexare 
-  * Funcții ​ 
-  * Agregarea datelor 
- 
-===== Indexare ===== 
- 
-MongoDB suport diferite tipuri de indecși. Indecși sunt utilizați pentru a crește performanțele operațiilor de căutare. Indecși sunt creați la nivel de colecție. Pentru a crea un index se folosește comanda ''​createIndex()''​. La creare se specifică numele câmpului (i.e., ''​label''​) și modul de ordonare a indexului (i.e., ''​order''​) 
-  * Indecși simpli ''​db.collection.createIndex({"​label":​ order})''​ 
-  * Indecși compusi ''​db.collection.createIndex({"​label_1":​ order_1, "​label_2":​ order_2, ...})''​ 
-  * Indecși pe documente imbricate: ''​db.collection.createIndex({"​label_1.nested_label":​ order_1, "​label_2.nested_label":​ order_2, ...})''​ 
-  * Indecși geo-spațiali ''​db.collection.createIndex({"​label_1.nested_label":​ "​2d"​})''​ 
-  * Indecși textuali (o colecție poate să aibă un singur index textual, dar acesta poate fi compus)''​db.collection.createIndex({"​label_1":​ "​text",​ "​label_2":​ "​text",​ ...})''​ 
-  * Indecși hashed (utili pentru sharding): ''​db.collection.createIndex({"​label":​ "​hashed"​})''​ 
- 
-Pentru următoarele exemple să se importe documentele din fișierul {{:​bd2:​laboratoare:​bd2_mongo.txt|bd2_mongo}} care conține baza de date în format JSON. Noua bază de date se va numi **BD2** și colecția se va numi **documents**. 
- 
-<color red>Ex. 1.</​color>​ Analizați schema documentelor și înțelegeți structura 
- 
-<code javascript>​ 
-db.documents.createIndex({author:​ 1}) 
-db.documents.createIndex({gender:​ 1, age: 1}) 
-db.documents.createIndex({"​words.word":​ 1}) 
-db.documents.createIndex({"​geoLocation":​ "​2d"​}) 
-db.documents.createIndex({"​lemmaText":​ "​text"​}) ​ 
-db.documents.createIndex({"​date":​ "​hashed"​}) 
-</​code>​ 
- 
-<color red>Ex. 2.</​color>​ Descrieți tipul indecșilor construiți anterior. 
- 
-<note important>​ 
-Pentru a vedea toți indecși se folosește comanda ''​db.collection.getIndexes()''​ 
- 
-Pentru a șterge un index se folosește comanda ''​db.collection.dropIndexes("​index_name"​)''​ 
- 
-Pentru a șterge toți indecși (cu excepția indexului de pe cheia primară) se folosește comanda ''​db.collection.dropIndexes()''​ 
-</​note>​ 
- 
-==== Utilizare indecși geo-spațiali ==== 
- 
-  * Pentru a găsi documentele de lângă un punct ''​p=[x,​ y]''​ se folosește ''​$near''​ 
-  * Pentru a găsi documentele care se găsesc în diferite figuri geometrice se folosește ''​$within'':​ 
-    * Pentru un cerc cu centrul într-un punct ''​p=[x,​ y]''​ și o rază ''​r''​ se folosește ''​$center''​ 
-    * Pentru un dreptunghi definit prin punctele din stânga jos și dreapta sus se folosește ''​$box''​ 
-    * Pentru un poligon dat de o listă puncte se folosește ''​$polygon''​ 
- 
-<code javascript>​ 
-db.documents.find( { geoLocation:​ { $near: [25, 25] } }, {geoLocation:​ 1} ) 
-db.documents.find( { geoLocation:​ { $within: { $center: [[25, 10], 3] } } }, {geoLocation:​ 1} ) 
-db.documents.find( { geoLocation:​ { $within: { $box: [[25, 40], [30, 45]] } } }, { geoLocation:​ 1 } ) 
-db.documents.find( { geoLocation:​ { $within: { $polygon: [[20, 40], [40, 50], [30, 30]] } } },  { geoLocation:​ 1 } ) 
-</​code>​ 
- 
-==== Utilizare indecși textuali ==== 
- 
-Pentur a utiliza un index textual se folosește următoare sintaxă: 
-<code javascript>​ 
-{ 
-  $text: 
-    { 
-      $search: <​string>,​ 
-      $language: <​string>,​ 
-      $caseSensitive:​ <​boolean>,​ 
-      $diacriticSensitive:​ <​boolean>​ 
-    } 
-} 
-</​code>​ 
- 
-Unde 
-  * ''​$search''​ - este șirul de cuvinte căutat sau fraza căutată 
-  * ''​$language''​ - este limba pentru cuvintele căutate 
-  * ''​$caseSensitive''​ - dacă se caută case sensitive sau nu 
-  * ''​$diacriticSensitive''​ - dacă se ține cont de diacritice sau nu 
- 
- 
-<code javascript>​ 
-# Caută un cuvânt 
-db.documents.find( { $text: { $search: "​coffee",​ $language: "​english",​ $caseSensitive:​ false, $diacriticSensitive:​ false } } ,  { lemmaText: 1 } ) 
- 
-# Caută mai multe cuvinte (se folosește operatorul or) 
-db.documents.find( { $text: { $search: "​coffee cup", $language: "​english",​ $caseSensitive:​ false, $diacriticSensitive:​ false } } ,  { lemmaText: 1 } ) 
- 
-# Caută o frază 
-db.documents.find( { $text: { $search: "​\"​heaven tonight\"",​ $language: "​english",​ $caseSensitive:​ false, $diacriticSensitive:​ false } } ,  { lemmaText: 1 } ) 
- 
-# Caută o frază cu un scor de relevanță 
-db.documents.find( { $text: { $search: "​\"​heaven tonight\"",​ $language: "​english",​ $caseSensitive:​ false, $diacriticSensitive:​ false } } ,  { score: { $meta: "​textScore"​ }, lemmaText: 1, _id: 0}) 
-</​code>​ 
- 
-<color red>Ex. 3.</​color>​ Să se găsească toate documentele care se află într-un dreptunghi dat de punctele ''​[20,​ -100]''​ și ''​[40,​ 90]'',​ care să conțină cuvintele **tech** și **engineering**. Cererea să se folosească de indexul textual. Afișeți câmpul **rawText**. Să se refacă cererea utilizând alt câmp din document. 
- 
-===== Funcții ===== 
- 
-MongoDB permite dezvoltatorilor sa scrie funcții folosind limbajul JavaScript. 
- 
-<color red>Ex. 4.</​color>​ Să se scrie o funcție care primește un **query** pentru filtrare și împarte **lemmaText** în cuvinte. Funcția va întoarce un vector. 
- 
-<code javascript>​ 
-tokenization = function(q){ 
-    var cursor = db.documents.find(q,​{"​_id":​ 0, lemmaText: 1}); 
-    var tokens = Array(); 
-    cursor.forEach(function(elem){ 
-        tokens = tokens.concat(elem["​lemmaText"​].split("​ ")); 
-    }); 
-    return tokens; 
-} 
- 
-// utilizate 
-var q = {gender: "​male"​} 
-tokens = tokenization(q) 
- 
-</​code>​ 
- 
-<color red>Ex. 5.</​color>​ Să se scrie o funcție numită **countWords** care primește un **query** pentru filtrare și numără aparițiile unui cuvânt. Funcția va întoarce un obiect de forma ''​{word_1:​ count, word_2: count, ...}''​. Folosiți funcția ''​tokenization''​. 
- 
- 
-==== Funcții stocate ==== 
- 
-Funcțiile pot fi stocate la nivelul MongoDB. Pentru acest lucru se folosește o colecție specială numită ''​system.js''​. Stocarea se face cu comanda: ''​db.system.js.save(_id:​ "​function_name",​ value: "​function_body"​)''​. Pentru a lucra cu funcțiile stocare (a le încărca în sesiune) se folosește comanda ''​db.loadServerScripts()''​. 
- 
-<code javascript>​ 
-db.system.js.save( 
-   { 
-     _id: "​tokenization",​ 
-     value : function(q){ 
-                var cursor = db.documents.find(q,​{"​_id":​ 0, lemmaText: 1}); 
-                var tokens = Array(); 
-                cursor.forEach(function(elem){ 
-                    tokens = tokens.concat(elem["​lemmaText"​].split("​ ")); 
-                }); 
-                return tokens; 
-            } 
-   } 
-) 
- 
-db.loadServerScripts() 
-</​code>​ 
- 
-<color red>Ex. 6.</​color>​ Salvați și apoi încărcați în sesiune funcția **countWords**. 
- 
-===== Agregarea datelor ===== 
- 
-În MongoDB putem să agregăm datele folosind mai multe metode: 
-  * Funcții de agregare 
-  * Modulul nativ de Aggregation Pipeline 
-  * MapReduce 
- 
-==== Funcții de agregare ==== 
- 
-MongoDB oferă utilizatorilor două funcții pentru agregare: 
- 
-1. Count: ''​db.collection.count(query)''​ 
- 
-<code javascript>​ 
-// Cate documente au lungimea textului lematizat 10 
-db.documents.count({lemmaTextLength:​ 10}) 
-</​code>​ 
- 
- 
-2. Distinct: db.collection.distinct(field,​ query)​ 
- 
-<code javascript>​ 
-// afiseaz varstele distincte 
-db.documents.distinct("​age"​) 
- 
-// afiseaz varstele distincte pentru female 
-db.documents.distinct("​age",​ {gender: "​female"​}).sort() 
-</​code>​ 
- 
-<color red>Ex. 7.</​color>​ Afișați toate cuvintele distincte. Folosiți câmpul **words**. 
- 
-==== Aggregation Pipeline ==== 
- 
-Pentru agregare, MongoDB oferă și **Aggregation Pipeline** ([[https://​docs.mongodb.com/​manual/​core/​aggregation-pipeline/​|Documentație]]). 
- 
-<code javascript>​ 
-db.collection.aggregate( 
-    { $match: <​query>​ }, 
-    { $unwind: <​array>​ }, 
-    { $project: <​projection>​},​ 
-    { $group: <​aggregation_group,​ aggregation_functions>​ }, 
-    { $sort: <​sorting_fields>​ }, 
-)​ 
-</​code>​ 
- 
-Unde: 
-  * $match - filtrează documentele de intrare după un **query** 
-  * $unwind - procesează elementele unui vector 
-  * $project - proiecția 
-  * $group - face grupuri și a aplica funcții agregare 
-  * $sort - reordonează documentele de intrare după o cheie 
- 
-<note important>​Contează ordinea în care sunt folosiți operatorii.</​note>​ 
- 
-<color red>Ex. 8.</​color>​ Să se utilizeze Aggregation Pipeline pentru a calcula numărul de apariții ale cuvintelor. 
- 
-<code javascript>​ 
-db.documents.aggregate([ 
-    { $match: q }, 
-    { $project: { words: { $split: ["​$lemmaText",​ " "]}}}, 
-    { $unwind: "​$words"​ }, 
-    { $group: { _id: "​$words",​ counts: { $sum: 1 } } } 
-]) 
-</​code>​ 
- 
-<color red>Ex. 9.</​color>​ Să se utilizeze Aggregation Pipeline pentru a calcula numărul de apariții ale cuvintelor folosind coloana **words**. 
- 
-==== MapReduce ==== 
- 
-MongoDB oferă un framework de MapReduce. Pentru a utiliza acest framework trebuie să scriem două funcții,​i.e.,​ Map și Reduce. ​ 
-Pentru a utilza funcțiile pe o colecție se folosește ''​mapReduce''​ ([[https://​docs.mongodb.com/​manual/​core/​map-reduce/​|Documentație]]):​ 
- 
- 
-<code javascript> ​ 
- 
-db.collection.mapReduce( 
-    mapFunction, ​ 
-    reduceFunction, ​ 
-    { 
-        finalize: <​function>,​ 
-        out: <​output>,​ 
-        query: <​document>,​ 
-        sort: <​document>,​ 
-        limit: <​number>,​ 
-        scope: <​document>​ 
-    } 
-) 
-</​code>​ 
- 
-Unde: 
-  * mapFunction - funcția de map 
-  * reduceFunction - funcția de reduce 
-  * finalize - (opțional) funcție pentru finalizare, se aplică după ce se termină procesul și datele sunt agregate 
-  * out -  (opțional) colecția unde va fi salvat rezultatul 
-  * query -  (opțional) filtru pentru documentele de intrare 
-  * sort - (opțional) ordonează documentele de intrare după cheie 
-  * limit - (opțional) limitează numărul de documente de intrare 
-  * scope -  (opțional) variabile din exterior care pot fi folosite în funcțiile map, reduce și finalize 
- 
-Comanda ''​mapReduce''​ este o mapare peste comanda **mapReduce** din MongoDB ([[https://​docs.mongodb.com/​manual/​reference/​command/​mapReduce/​|Documentație]]) 
- 
-<code javascript>​ 
-db.runCommand( 
-    { 
-        mapReduce: <​collection>,​ 
-        map: <​function>,​ 
-        reduce: <​function>,​ 
-        finalize: <​function>,​ 
-        out: <​output>,​ 
-        query: <​document>,​ 
-        sort: <​document>,​ 
-        limit: <​number>,​ 
-        scope: <​document>​ 
-    } 
-) 
-</​code>​ 
- 
- 
-<color red>Ex. 10.</​color>​ Să se utilizeze MapReduce pentru a calcula numărul de apariții ale cuvintelor. 
- 
-<code javascript>​ 
-mapFunction = function() { 
-    var tokens = this.lemmaText.split("​ "); 
-    for (var idx=0; idx<​tokens.length;​ idx++){ 
-        emit(tokens[idx],​ 1); 
-    } 
-} 
-    ​ 
-reduceFunction = function(key,​ values) { 
-    return Array.sum(values);​ 
-}; 
-  ​ 
-var q = {"​gender":​ "​female"​} ​       
-db.documents.mapReduce(mapFunction,​ reduceFunction,​ {query: q, out: "​wordCounts"​});​ 
- 
-db.wordCounts.count() 
- 
-db.wordCounts.find({"​_id":​ "​0"​}) 
- 
-db.wordCounts.drop() 
-</​code>​ 
- 
-<color red>Ex. 11.</​color>​ Să se utilizeze MapReduce pentru a calcula numărul de apariții ale cuvintelor folosind câmpul **words**. 
bd2/laboratoare/12.1575718549.txt.gz · Last modified: 2019/12/07 13:35 by ciprian.truica
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0