Sunteți pe pagina 1din 13

MANAGEMENTUL COLECȚIILOR DE DOCUMENTE ÎN MONGODB

1. Configurarea mediului de lucru și accesul la colecțiile de date

Descărcați și instalați NoSQLBooster for MongoDB (https://nosqlbooster.com/downloads).


In salile de seminar NoSQL Booster este instalat.

Se poate utiliza și Mongo Shell sau un alt instrument vizual pentru interogarea documentelor.

Deschideți NoSQLBooster for MongoDB și creați o nouă conexiune cu serverul de Mongo


DB:

In secțiunea Connection Tree se pot accesa bazele de date și colecțiile stocate în Mongo DB.

Regasirea datelor în Mongo DB se realizează prin metodele find() în care se precizează


condițiile de regăsire și projection() în care sunt precizate atributele care vor fi afișate. Pentru
ordonarea datelor este utilizată metoda sort().

1
Parametrii metodei projection() sunt atributele (câmpurile) care vor fi afișate urmate de :0 în
cazul în care dorim să nu afișam câmpul sau :1 în cazul în care dorim ca acel câmp să fie
inclus în vizualizare. Doar atributul _id poate fi exclus în cazul în care avem câmpuri
precizate cu valoarea :1.

Pentru a afișa anumite câmpuri, acestea se pot specifica și în metoda find(), după criteriul de
regăsire.

De exemplu, pentru a afișa MARCA și MODELUL tuturor autoturismelor pentru care s-au
înregistrat daune se poate utiliza comanda:

db.clienti_daune.find({ },{MARCA: 1, MODEL: 1})

similară cu:

db.clienti_daune.find({ }).projection ({MARCA: 1, MODEL: 1})

Implicit vizualizarea este de tip arbore de documente (TREE), însă poate fi schimbată prin
selectarea tipului TABLE din lista derulantă (TREE).

Ordonarea datelor se realizează cu metoda sort() specificând modalitatea ascendentă key:1


sau descendentă key:-1.

De exemplu, pentru afișarea în ordinea crescătoare a mărcilor auto:

db.clienti_daune.find({}).projection({TARAPRODUCATOR:1,
REGIUNEPRODUCATOR:1, MARCA:1, MODEL:1,
DAUNA:1}).sort({MARCA:1})

Criteriile de selecție pot fi combinate utilizând operatorii: $and, $or.

De exemplu, pentru a afișa câmpurile TARAPRODUCATOR, REGIUNEPRODUCATOR,


MARCA, MODEL produse în regiunea ‘Europe’ care contin litera ‘F’, ornonate descrescător
în funcție de MARCA și crescător în funcție de MODEL, se utilizează comanda:

2
db.clienti_daune

.find({$and: [{REGIUNEPRODUCATOR:'Europe'},{MARCA:/F/}]})

.projection({_id:0,TARAPRODUCATOR:1, REGIUNEPRODUCATOR:1,
MARCA:1, MODEL:1})

.sort({MARCA:-1, MODEL:1})

Comentariile se pot introduce pe linie folosind //

2. Regăsirea documentelor.

Metoda find() are corespondență cu clauza WHERE din SQL.

Paralela între metoda find() și condițiile din clauza WHERE:


https://docs.mongodb.com/manual/reference/sql-comparison/ sau
https://www.tutorialspoint.com/mongodb/mongodb_query_document.htm

Exerciții: Rezolvați următoarele cerințe exprimate în SQL:

SQL SELECT MongoDB find()


SELECT *
db.clienti_daune.find({})
FROM clienti_daune
SELECT _id,
MARCA,
db.clienti_daune.find({ }).projection ({MARCA:
MODEL,
1, MODEL: 1, PRET_MANOPERA:1})
PRET_MANOPERA
FROM clienti_daune
SELECT MARCA,
db.clienti_daune.find({ }).projection ({MARCA:
MODEL,
1, MODEL: 1, PRET_MANOPERA:1, _id: 0 })
PRET_MANOPERA
//exclude indexul _id
FROM clienti_daune
SELECT MARCA,
MODEL,
db.clienti_daune.find({ TARA_FURNIZOR: "UK" },
TARA_FURNIZOR
{MARCA:1, MODEL:1,TARA_FURNIZOR:1, _id:0})
FROM clienti_daune
WHERE TARA_FURNIZOR = ‘UK’
SELECT MARCA,
MODEL,
TARA_FURNIZOR db.clienti_daune.find({
FROM clienti_daune TARA_FURNIZOR: {$in: ["UK", "US"]}}, {MARCA:
WHERE TARA_FURNIZOR in 1, MODEL: 1, TARA_FURNIZOR: 1, _id:
(‘UK’, ‘US’) 0}) .sort({TARA_FURNIZOR:-1})
ORDER BY TARA_FURNIZOR desc

SELECT MARCA, db.clienti_daune.find({


MODEL, TARA_FURNIZOR: {$nin: ["UK", "US"]}}, { MARCA:
TARA_FURNIZOR 1, MODEL: 1, TARA_FURNIZOR: 1, _id: 0 })
FROM clienti_daune .sort({ TARA_FURNIZOR: -1 })
WHERE TARA_FURNIZOR not in
(‘UK’, ‘US’)

3
SQL SELECT MongoDB find()
ORDER BY TARA_FURNIZOR desc
SELECT MARCA,
MODEL,
db.clienti_daune.find({
TARAPRODUCATOR,
TARAPRODUCATOR: {$ne: "United States"}
VALOARE_DAUNA
}, { MARCA: 1, MODEL: 1, TARAPRODUCATOR:
FROM clienti_daune
1, VALOARE_DAUNA: 1, _id: 0 })
WHERE TARAPRODUCATOR !
.sort({ TARAPRODUCATOR: -1 })
=’United States’
ORDER BY TARAPRODUCATOR desc
db.clienti_daune.find({ MARCA: "JEEP",
SELECT * AN_FABRICATIE: "2010" })
FROM clienti_daune
WHERE MARCA = ‘JEEP’ //sau cu operatorul $and:[{}]
AND AN_FABRICATIE = 2010
db.clienti_daune.find({$and: [{MARCA: "JEEP",
AN_FABRICATIE: 2010}]})
SELECT *
db.clienti_daune.find({$or: [{MARCA: "JEEP",
FROM clienti_daune
AN_FABRICATIE: 2010}]})
WHERE MARCA = ‘JEEP’
OR AN_FABRICATIE = 2010
SELECT MARCA, MODEL,
VALOARE_DAUNA
db.clienti_daune.find({VALOARE_DAUNA:{$gt:
FROM clienti_daune
500}}, { MARCA: 1, MODEL: 1, VALOARE_DAUNA: 1,
WHERE VALOARE_DAUNA > 500
_id: 0 }). sort({VALOARE_DAUNA:1})
ORDER BY VALOARE_DAUNA

SELECT MARCA, MODEL,


VALOARE_DAUNA db.clienti_daune.find({VALOARE_DAUNA:{$lt:
FROM clienti_daune 500}}, { MARCA: 1, MODEL: 1, VALOARE_DAUNA: 1,
WHERE VALOARE_DAUNA < 500 _id: 0 }). sort({VALOARE_DAUNA:1})
ORDER BY VALOARE_DAUNA
SELECT MARCA, MODEL,
VALOARE_DAUNA db.clienti_daune.find({VALOARE_DAUNA:{$gt:
FROM clienti_daune 500, $lt:510}}, { MARCA: 1, MODEL: 1,
WHERE VALOARE_DAUNA > 500 VALOARE_DAUNA: 1, _id: 0 }).
AND VALOARE_DAUNA < 510 sort({VALOARE_DAUNA:1})
ORDER BY VALOARE_DAUNA
SELECT MARCA, MODEL,
VALOARE_DAUNA db.clienti_daune.find({VALOARE_DAUNA:{$gte:
FROM clienti_daune 500, $lte:510}}, { MARCA: 1, MODEL: 1,
WHERE VALOARE_DAUNA between VALOARE_DAUNA: 1, _id: 0 }).
500 AND 510 ORDER BY sort({VALOARE_DAUNA:1})
VALOARE_DAUNA
db.clienti_daune.find({DAUNA: /LIGHTS/})

//sau
SELECT *
FROM clienti_daune db.clienti_daune.find( { DAUNA: { $regex:
WHERE DAUNA like ‘%LIGHTS%’ /LIGHTS/ } } )

//sau
db.clienti_daune.find({
DAUNA: mb.regex.contains("LIGHTS")})
SELECT * db.clienti_daune.find( { DAUNA: /^WARNING/})
FROM clienti_daune
WHERE DAUNA like ‘WARNING%’ //sau

db.clienti_daune.find( { DAUNA: { $regex:

4
SQL SELECT MongoDB find()
/^WARNING/ } } )
SELECT * db.clienti_daune.find({
FROM clienti_daune DAUNA: mb.regex.endsWith("LIGHT")
WHERE DAUNA like ‘%LIGHT’ })
db.clienti_daune.count()
SELECT COUNT(*)
FROM clienti_daune //sau

db.clienti_daune.find().count()
db.clienti_daune.count( { MARCA: { $exists:
SELECT COUNT(MARCA) true } } )
FROM clienti_daune //sau
db.clienti_daune.find( { MARCA: { $exists:
true } } ).count()
db.clienti_daune.count( { VALOARE_DAUNA:
SELECT COUNT(*) { $gt: 500 } } )
FROM clienti_daune
WHERE VALOARE_DAUNA > 500 //sau

db.clienti_daune.find( { VALOARE_DAUNA: { $gt:


500 } } ).count()
db.clienti_daune.aggregate( [ { $group : { _id
SELECT DISTINCT(MARCA) : "$MARCA" } } ] )
FROM clienti_daune
//sau

db.clienti_daune.distinct("MARCA")
SELECT *
FROM clienti_daune db.clienti_daune.find().limit(200)
LIMIT 200
SELECT *
FROM clienti_daune db.clienti_daune.find().limit(5).skip(10)
LIMIT 5
SKIP 10

Determinarea unor expresii


Metoda aggregate() permite agregarea datelor în vederea determinării unor valori calculate.
Pentru calcularea unor valori sau realizarea unor expresii se pot adăuga noi atribute în
interogare cu ajutorul clauzei:
{ $addFields: { <newField>: <expression>, ... } }

De exemplu, pentru determinarea valorii componentelor (materialelor) necesare reparațiilor


scădem pretul manoperei din valoarea totală a daunei:

SQL:

SELECT MARCA, MODEL, VALOARE_DAUNA


,VALOARE_DAUNA-PRET_MANOPERA AS PRET_MATERIALE
FROM clienti_daune;

MongoDB:
5
db.clienti_daune.aggregate( [

{$addFields: { Pret_materiale: { $subtract: ["$VALOARE_DAUNA",


"$PRET_MANOPERA" ] } }},

{$project: {MARCA:1, MODEL:1, VALOARE_DAUNA:1, Pret_materiale:1, _id:0}}

])

În acest caz metoda projection() se va transforma în clauza $project:{}, iar metoda


find() în clauza $match:{}.

De exemplu, modificăm interogarea de mai sus astfel încât să calculăm pretul materialelor
doar pentru autoturismele marca FORD:

SQL:

SELECT MARCA, MODEL, VALOARE_DAUNA


,VALOARE_DAUNA-PRET_MANOPERA AS PRET_MATERIALE
FROM clienti_daune
WHERE MARCA=’FORD’;

MongoDB:

db.clienti_daune.aggregate( [
{$match:{MARCA:'FORD'}},
{$addFields: {Pret_materiale: {$subtract: ["$VALOARE_DAUNA",
"$PRET_MANOPERA"]}}},
{$project: {MARCA:1, MODEL:1, VALOARE_DAUNA:1, Pret_materiale:1,
_id:0}}
])

Se pot realiza expresii alternative folosind clauza $switch: {} similară lui CASE din SQL.
De exemplu, putem adăuga un nou câmp CATEGORIE_DAUNA care să aibă valoarea "mare"
dacă valoarea daunei este peste 1000$, "medie" dacă valoare mai mare decât 500$ dar mai
mică decât 1000$ și "mică" dacă valoarea daunei este sub 500$.

MongoDB:

db.clienti_daune.aggregate( [
{$addFields: {Pret_materiale: { $subtract: ["$VALOARE_DAUNA",
"$PRET_MANOPERA" ] },
Categorie_dauna: {
$switch: {
branches: [
{ case: { $gt: [ "$VALOARE_DAUNA", 1000 ] }, then: "mare" },
{ case: { $gt: [ "$VALOARE_DAUNA" , 500 ] }, then: "medie" },
],
default: "mica" }

6
}
}},
{$match:{MARCA:'FORD'}},
{$project: {MARCA:1, MODEL:1, VALOARE_DAUNA:1,
Pret_materiale:1,Categorie_dauna:1, _id:0}}
])

3. Agregarea datelor

3.1. Agregări de tip Pipeline (Aggregation Pipeline)

În MongoDB, agregările sunt procesate sub forma unui flux de tip pipeline implementat prin
metoda aggregate() în care o listă de operatori / filtre sunt aplicate datelor. Fluxul de
prelucrare conține etapele de filtrare ($match: {conditii pentru câmpuri}), grupare
($group: { _id: { key1: "$Alias1", key2: "$Alias2" } ) și ordonare ($sort:
{ Alias1: -1, Alias2:1 }), iar în cazul în care se restricționează documentele din
grupurile formate (similar cu clauza HAVING din SQL) se utilizează etapa de filtrare pe
grupuri ($match: {conditii pentru grupuri}):

{
MARCA: "FORD",
VAL_DAUNA:500
}
{
MARCA: "FORD",
VAL_DAUNA:500
}
 

{
MARCA: "FORD",
VAL_DAUNA:300
}
 
{
MARCA: "FORD", {
VAL_DAUNA:300 MARCA: "FORD",
} VAL_DAUNA:800
  }
  {
{ MARCA: "FORD",
MARCA: "AUDI", VAL_DAUNA:800
VAL_DAUNA:200 }
}  
  $match: {MARCA:{$in:["FORD","JEEP"]}
$group : {_id : { marca: "$MARCA"} $match: {VAL_DAUNA: { $gte: 800} }
{
MARCA: "JEEP", {
VAL_DAUNA:500 MARCA: "JEEP",
} VAL_DAUNA:750
  }
 
{
MARCA: "JEEP",
VAL_DAUNA:500
}
 
{
MARCA: "JEEP",
VAL_DAUNA:250
}
 
{
MARCA: "JEEP",
VAL_DAUNA:250
}
 

7
Sintaxa generala este următoarea:

db.col.aggregate( [
{ $match: { conditii pentru keys} },

{ $group: { _id: { key1: "$Alias1", key2: "$Alias2" },


count: { $sum: 1 }, suma:{$sum:key3},medie:{$avg:key4} } },
{ $match: { conditii pentru grup} },
{ $project: { _id: 0,
key1: "$_id.Alias1",
key2: "$_id.Alias2",
count: 1,………..},
{ $sort: { Alias1: -1, Alias2:1 }}

] )

De exemplu, pentru afișarea numărului de daune, a valorilor medii și totale pe fiecare marcă
și model utilizăm comanda:

SQL:

SELECT marca, model, avg(VALOARE_DAUNA), sum(VALOARE_DAUNA), count(VIN)


FROM clienti_daune GROUP BY marca, model;

MongoDB:

db.clienti_daune.aggregate([{$group : {
_id : { marca: "$MARCA",model:"$MODEL"},
valoare_medie_dauna: { $avg: "$VALOARE_DAUNA" },
valoare_daune: { $sum: "$VALOARE_DAUNA" },
nr_daune: { $sum: 1 } }}])

Ordonarea valorilor agregate se realizează cu clauza $sort care recunoaște noile expresii
(alias):

db.clienti_daune.aggregate(
[ {$group : {
_id : { marca: "$MARCA",model:"$MODEL"},
valoare_medie_dauna: { $avg: "$VALOARE_DAUNA" },
valoare_daune: { $sum: "$VALOARE_DAUNA" },
nr_daune: { $sum: 1 }
}},
{ $sort: { nr_daune: -1 } }
])

8
În cazul agregărilor, criteriile de selecție se precizează în clauza match{} și nu în find().

De exemplu, pentru calcularea daunelor medii și totale în cazul mărcilor FORD și JEEP
fabricate între 2010 și 2012 se utilizează comanda:

SQL:

SELECT marca, model, avg(VALOARE_DAUNA), sum(VALOARE_DAUNA), count(VIN)


FROM clienti_daune
WHERE MARCA in (’FORD’,’JEEP’) and AN_FABRICATIE between 2010 and 2012
GROUP BY marca, model
ORDER BY count(VIN);

MongoDB:

db.clienti_daune
.aggregate(
[ {$match: {MARCA:{$in:["FORD","JEEP"]}, AN_FABRICATIE: { $gte:
2010, $lte: 2012 } } },
{$group : {
_id : { marca: "$MARCA",model:"$MODEL"},
valoare_medie_dauna: { $avg: "$VALOARE_DAUNA" },
valoare_daune: { $sum: "$VALOARE_DAUNA" },
nr_daune: { $sum: 1 }
}},
{ $sort: { nr_daune: -1 } }
])

Pentru limitarea rezultatelor, vom returna doar grupurile pentru care nr de daune este cuprins
între 100 și 400. În acest caz clauza {$match:{ }} este utilizată de două ori:

SQL:

SELECT marca, model, avg(VALOARE_DAUNA), sum(VALOARE_DAUNA), count(VIN)


FROM clienti_daune
WHERE MARCA in (’FORD’,’JEEP’) and AN_FABRICATIE between 2010 and 2012
GROUP BY marca, model
HAVING count(VIN) between 100 and 400
ORDER BY count(VIN);

MongoDB:

db.clienti_daune.aggregate(

9
[ {$match: {MARCA:{$in:["FORD","JEEP"]},AN_FABRICATIE: { $gte:
2010, $lte: 2012 } }} ,
{$group : {
_id : { marca: "$MARCA",model:"$MODEL"},
valoare_medie_dauna: { $avg: "$VALOARE_DAUNA" },
valoare_daune: { $sum: "$VALOARE_DAUNA" },
nr_daune: { $sum: 1 }
}},
{$match: {nr_daune: { $gte: 100, $lte: 400 } }} ,
{ $sort: { nr_daune: -1 } }
])

În cazul în care dorim să grupăm toate documentele, în clauza $group identificatorul _id va fi
null. De exemplu, pentru a afișa numărul și valoarea totală a daunelor utilizăm comanda:

SQL:

SELECT COUNT(*) AS nr_daune, SUM(VALOARE_DAUNA) AS valoare_totala


FROM clienti_daune;

MongoDB:

db.clienti_daune.aggregate([ {$group : {_id : null,


valoare_totala_daune: { $sum: "$VALOARE_DAUNA" },
nr_daune: { $sum: 1 }}}])

Pentru excluderea documentelor pentru care valoarea daunei este sub 100$ putem utiliza
clauza $match:

SQL:

SELECT COUNT(*) AS nr_daune, SUM(VALOARE_DAUNA) AS valoare_totala


FROM clienti_daune
WHERE VALOARE_DAUNA>100;

MongoDB:

db.clienti_daune.aggregate(
[ {$match:{VALOARE_DAUNA:{$gt:100}}},
{$group : {
_id : null,
valoare_totala_daune: { $sum: "$VALOARE_DAUNA" },

10
nr_daune: { $sum: 1 }
}}
])

3.2. Agregări avansate

Gruparea datelor în loturi (buckets)

Clauza $bucket (aggregation) împarte documentele primite în grupuri, numite buckets, pe


baza unei expresii specificate și a unor limite. Fiecare bucket va forma un document de ieșire
care conține un identificator _id, a cărui valoare specifică limita inferioară grupului și un total
care precizează numărul de documente din bucket. Sintaxa este următoarea:

{
$bucket: {
groupBy: <expression>,
boundaries: [ <lowerbound1>, <lowerbound2>, ... ],
default: <literal>,
output: {
<output1>: { <$accumulator expression> },
...
<outputN>: { <$accumulator expression> }
}
}
}

De exemplu, pentru a grupa autoturismele în funcție de valoarea daunelor pe intervalele 0-


100, 100-200, 200-400, 400-600, 600-800, 800-1000 și a realiza sub-liste cu denumirea
mărcii, a modelului și a anului de fabricație se utilizează comanda:

db.clienti_daune.aggregate( [
{
$bucket: {
groupBy: "$VALOARE_DAUNA",
boundaries: [ 0, 100, 200, 400, 600, 800, 1000 ],
default: "Other",
output: {
"Nr_total": { $sum: 1 },
"Marci cu daune" : { $push: { Marca: "$MARCA", Model: "$MODEL",An:
"$AN_FABRICATIE", Valoare:"$VALOARE_DAUNA" }}
}
}
}
] )

11
Colecția rezultată este formată dintr-un identificator _id cu valorile precizate în clauza
boundaries, un câmp cu numărul total al autoturismelor din acel interval (bucket) și un nou
câmp de tip listă de documente cu denumirea mărcii, modelului, anul de fabricație și
valoarea corespunzătoare a daunei.

Clauza $facet procesează mai multe fluxuri de agregare de tip pipeline pe același set de
documente. Fiecare flux furnizează documente separate de ieșire.

Sintaxa este următoarea:

{$facet:
{
<outputField1>: [<stage1>, <stage2>, ... ],
<outputField2>: [<stage1>, <stage2>, ... ],
...
}
}
Clauza $facet se poate combina cu clauza $bucket. În exemplul următor se procesează 2
fluxuri de agregare prin care se obțin 2 seturi de documente, primul în care daunele sunt
grupate în buckets în funcție de valoarea lor, și un alt set în care daunele sunt grupate în
funcție de anul de fabricație.

db.clienti_daune.aggregate(
[{
$facet: {
"Valoare":
[{
$bucket: {
groupBy: "$VALOARE_DAUNA",
boundaries: [0,100, 200, 400, 600, 800, 1000],

12
default: "Other",
output: {
"Nr_total": { $sum: 1 },
"Marci cu daune": { $push: { Marca: "$MARCA",
Model: "$MODEL", An: "$AN_FABRICATIE", Valoare: "$VALOARE_DAUNA" } }
}
}
}],
"An": [{
$bucket: {
groupBy: "$AN_FABRICATIE",
boundaries: [2008, 2010, 2012],
default: "Other",
output: {
"Nr_total": { $sum: 1 },
"Marci cu daune": { $push: { Marca: "$MARCA",
Model: "$MODEL", An: "$AN_FABRICATIE", Valoare: "$VALOARE_DAUNA" } }
}
}
}]
}
}])

Mai multe referințe: https://docs.mongodb.com/manual/

13

S-ar putea să vă placă și