This shows you the differences between two versions of the page.
bd2:laboratoare:11 [2019/12/09 11:59] ciprian.truica [Modificarea datelor] |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Laboratorul 11 - MongoDB I ====== | ||
- | |||
- | ===== Obiective ===== | ||
- | |||
- | * Comenzi MongoDB | ||
- | * Operații DML | ||
- | |||
- | ===== Path pentru MongoDB pe Windows ===== | ||
- | |||
- | "C:\Program Files\mongodb*\bin" | ||
- | |||
- | Dupa ca in laborator. | ||
- | |||
- | ===== Comenzi MongoDB ===== | ||
- | |||
- | ==== Pornire MongoDB ==== | ||
- | |||
- | Pentru a porni baza de date MongoDB se va folosi demonul **mongod**([[https://docs.mongodb.com/manual/reference/program/mongod/|mongod]]). | ||
- | |||
- | Procesul demon **mongod** poate porni cu următorii paramterii: | ||
- | |||
- | * **''-''''-''config <filename>** specifică un fisier de configurare | ||
- | * **''-''''-''port <port>** pentru a specifica portul pe care asculta procesul demon, implicit 27017 | ||
- | * **''-''''-''bind_ip <hostnames|ipaddresses|Unix domain socket paths>** pentru a specifica addresa de | ||
- | * **''-''''-''dbpath <path>** calea către directorul unde se vor stoca fișierele de stocare. | ||
- | |||
- | Exemplu utilizare **mongodb** | ||
- | |||
- | <code bash> | ||
- | mongod --port 27018 --bind_ip 192.100.10.10 --dbpath /data | ||
- | </code> | ||
- | |||
- | <color red>Ex. 1.</color> Să creeze un director pe discul ''Student'' numit ''mongo_data''. Să se pornească baza de date cu folosind ca director de stocare noul director creat. Restul valorilor rămân cele implicite. | ||
- | |||
- | ==== Conectare MongoDB ==== | ||
- | |||
- | Pentru a va conecta la un server MongoDB, se folosește interpretorul în linie de comandă **mongo** ([[https://docs.mongodb.com/manual/mongo/|Documentație]]). | ||
- | |||
- | Exemplu de utilizare: | ||
- | |||
- | <code bash> | ||
- | # se conectează implicit la localhost pe portul 27017 | ||
- | mongo | ||
- | |||
- | # se conectează la hostname folosind portul implicit 217017 | ||
- | mongo --host hostname | ||
- | |||
- | # se conectează implicit la localhost folosind portul port | ||
- | mongo --port 27017 | ||
- | |||
- | # se conectează la hostname folosind portul port | ||
- | mongo --host hostname:27017 | ||
- | |||
- | mongo --host hostname --port 27017 | ||
- | |||
- | </code> | ||
- | |||
- | <color red>Ex. 2.</color> Conectați-vă la MongoDB. | ||
- | |||
- | ==== Comenzi CLI MongoDB ==== | ||
- | |||
- | Pentru a vedea baza de date curentă se folosește comanda **db**. | ||
- | |||
- | Pentru a vedea toate bazele de date existente se folosește comanda **show dbs**. | ||
- | |||
- | Pentru a vă conecta la o baza de date sau a crea o nouă bază de date se folosește comanda **use DATABASE_NAME**. În cazul în care se folosește comanda **use** pentru a crea o bază de date, aceasta va deveni persistentă numai dacă se crează o colecție sau se inserează o înregistrare. | ||
- | |||
- | Pentru a vedea toate colecțiile se folosește comanda **show collections**. | ||
- | |||
- | Puteți folosi una din următoarele metode pentru a crea o nouă colecție: | ||
- | * **db.createCollection("COLLECTION_NAME")**, unde **COLLECTION_NAME** este numele noii colecții | ||
- | * inserați o înregistrare și colecția se va crea automat. | ||
- | |||
- | Pentru a șterge o colecție se folosește comanda **db.COLLECTION_NAME.drop()**. | ||
- | |||
- | Pentru a șterge o baza de date se folosește comanda **db.dropDatabase()**. Trebuie să fiți conectați la baza de date (folosing **use**) pentru a o șterge. | ||
- | |||
- | <note important>Numele bazelor de date este case sensitive.</note> | ||
- | |||
- | <color red>Ex. 3.</color> Creați o bază de date numită **faculty** care să conțină colecția **students**. | ||
- | |||
- | |||
- | ===== Operații DML ===== | ||
- | |||
- | ==== Inserarea datelor ==== | ||
- | |||
- | Pentru a adăuga date în MongoDB puteți sa folosiți una din metodele: | ||
- | |||
- | * Insert sau Bulk Insert ([[https://docs.mongodb.com/manual/reference/method/db.collection.insert/|Documentație]]) | ||
- | * **mongoimport** ([[https://docs.mongodb.com/manual/reference/program/mongoimport/|Documentație]]) | ||
- | |||
- | === insert() === | ||
- | |||
- | Comanda Insert are următoare sintaxa | ||
- | |||
- | <code javascript> | ||
- | db.collection.insert( | ||
- | <document or array of documents>, | ||
- | { | ||
- | writeConcern: <document>, | ||
- | ordered: <boolean> | ||
- | } | ||
- | ) | ||
- | </code> | ||
- | |||
- | Un document dintr-o colecție este în format BSON: | ||
- | |||
- | <code javascript> | ||
- | { | ||
- | "student": | ||
- | { | ||
- | "firstname": "Ion", | ||
- | "lastname": "Popescu" | ||
- | }, | ||
- | "an": 4, | ||
- | "grupa": "342C3", | ||
- | "materii": | ||
- | [ | ||
- | {"nume": "BD2", "an": 4}, | ||
- | {"nume": "Comp", "an": 4}, | ||
- | {"nume": "SO2", "an": 4} | ||
- | ], | ||
- | "cunostinte": ["SQL", "Java", "PL/SQL"] | ||
- | } | ||
- | |||
- | </code> | ||
- | |||
- | Pentru a insera documentul în colecția students: | ||
- | |||
- | <code javascript> | ||
- | db.students.insert( | ||
- | { | ||
- | "student": | ||
- | { | ||
- | "firstname": "Ion", | ||
- | "lastname": "Popescu" | ||
- | }, | ||
- | "an": 4, | ||
- | "grupa": "342C3", | ||
- | "materii": | ||
- | [ | ||
- | {"nume": "Comp", "an": 4}, | ||
- | {"nume": "BD2" , "an": 4}, | ||
- | {"nume": "SO2" , "an": 4} | ||
- | ], | ||
- | "cunostinte": ["SQL", "Java", "PL/SQL"] | ||
- | } | ||
- | ) | ||
- | </code> | ||
- | |||
- | Pentru a va ușura munca puteți sa va creați variabile la nivelul consolei. Dacă se dorește inserarea mai multor înregistrari, se poate declara un vector. | ||
- | |||
- | <code javascript> | ||
- | var stud = {"student": { "firstname": "Andrei", "lastname": "Ionescu"}, "an": 4, "grupa": "341C4", "materii": [{"nume": "BD2", "an": 4}, {"nume": "IA", "an": 4},{"nume": "IAUT", "an": 4}], "cunostinte": ["C", "C++", "SQL"] } | ||
- | |||
- | db.students.insert(stud) | ||
- | |||
- | var studs = [ | ||
- | {"student": { "firstname": "George", "lastname": "Popescu"}, "an": 4, "grupa": "341C2", "materii": [{"nume": "BD2", "an": 4}, {"nume": "IOCLA", "an": 2}], "cunostinte": ["Python", "SQL"] }, | ||
- | {"student": { "firstname": "Georgiana", "lastname": "Petrescu"}, "an": 4, "grupa": "341C2", "materii": [{"nume": "BD2", "an": 4}, {"nume": "SCAD", "an": 4}], "cunostinte": ["Python", "SQL"] }, | ||
- | {"student": { "firstname": "Valentina", "lastname": "Vasilescu"}, "an": 3, "grupa": "331CA", "materii": [{"nume": "BD", "an": 3}, {"nume": "RL", "an": 3}, {"nume": "APD", "an": 2}], "cunostinte": ["Java", "C++", "SQL"] }, | ||
- | {"student": { "firstname": "Grigore", "lastname": "Ionescu"}, "an": 4, "grupa": "342C2", "materii": [{"nume": "BD2", "an": 4}, {"nume": "VLSI", "an": 4}, {"nume": "SRIC", "an": 4}, {"nume": "SO", "an": 3}], "cunostinte": ["C", "Python", "SQL", "Ruby"] }, | ||
- | {"student": { "firstname": "Andrei", "lastname": "Popescu"}, "an": 3, "grupa": "332CA", "materii": [{"nume": "CN1", "an": 2}, {"nume": "CN2", "an": 2}, {"nume": "RL", "an": 3}], "cunostinte": ["C", "Python", "SQL", "Ruby"] }, | ||
- | {"student": { "firstname": "Ana", "lastname": "Georgescu"}, "an": 4, "grupa": "342C5", "materii": [{"nume": "BD2", "an": 4}, {"nume": "UBD", "an": 4}, {"nume": "SRIC", "an": 4}, {"nume": "SO", "an": 3}], "cunostinte": ["C", "Python", "SQL", "Ruby"], "sef": true }, | ||
- | ] | ||
- | |||
- | db.students.insert(studs) | ||
- | </code> | ||
- | |||
- | <color red>Ex. 4.</color> Inserați în baza de date **faculty** în colecția **students** folosind structura JSON de mai sus doi colegi și pe dumneavoastră. | ||
- | |||
- | === mongoimport === | ||
- | |||
- | Pentru a insera un fișier în format CSV sau JSON se folosește comanda **mongoimport**. | ||
- | Parametrii comenzii sunt: | ||
- | * ''-''''-host=<hostname><:port>'' - specifică numele host-ului și portul. Dacă nu se specifică se vor lua valorile implicite | ||
- | * ''-''''-port=<port>'' - specifică portul. Dacă nu se specifică se va lua valoarea implicită | ||
- | * ''-''''-db=<databasename>'' - specifică numele bazei de date unde se vor insera datele | ||
- | * ''-''''-collection=<collection>'' - specifică numele colecției care va stoca datele | ||
- | * ''-''''-fields=<field1[,field2]>'' - specifică câmpurile din fișier care for fi inserate în colecție | ||
- | * ''-''''-columnsHaveTypes'' - se utilizează dacă se dorește specificarea tipurilor de date pentru coloanele din lista de coloane specificată cu opțiunea ''-''''-fields'' | ||
- | * ''-''''-type=<json|csv|tsv>'' - specifică formatul fișierului cu date | ||
- | * ''-''''-file=<filename>'' - specifică numele fișierului cu date | ||
- | |||
- | |||
- | <code bash> | ||
- | mongoimport --host=192.100.10.2 --port=28018 --db=BD --collection=students --type=json --file=data_dump.json | ||
- | |||
- | mongoimport --host=192.100.10.2 --port=28018 --db=BD --collection=students --columnsHaveTypes --fields="name.string(),birthdate.date(2006-01-02),contacted.boolean(),followerCount.int32(),thumbnail.binary(base64)" --type=csv --file=data_dump.csv | ||
- | </code> | ||
- | |||
- | <color red>Ex. 5.</color> Să se insereze 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**. | ||
- | |||
- | |||
- | ==== Selectarea datelor ==== | ||
- | |||
- | === Select === | ||
- | |||
- | În MongoDB operația de selecție a datelor este **find()** ([[https://docs.mongodb.com/manual/reference/method/db.collection.find/|Documentație]]). | ||
- | |||
- | Sintaxa comenzii este: | ||
- | |||
- | <code javascript> | ||
- | db.collection.find(query, projection) | ||
- | </code> | ||
- | |||
- | Unde | ||
- | * ''query'' reprezintă lista de filtre | ||
- | * ''projection'' reprezintă câmpurile care vor fi afișate | ||
- | |||
- | Dacă parametrul ''query'' lipsește, atunci se selectează toate documentele. Dacă parametrul ''projection'' lipsește atunci se afișează toate câmpurile documentului. | ||
- | |||
- | Comanda **find()** face paginație, arătând în consolă 10 înregistrări. | ||
- | |||
- | Să se selecteze toți studenții din colecția **students**, baza de date **faculty** | ||
- | <code javascript> | ||
- | db.students.find() | ||
- | </code> | ||
- | |||
- | |||
- | <note tip> | ||
- | * Dacă se dorește întoarcerea unei singur document se folosește **findOne()** | ||
- | <code javascript> | ||
- | db.students.findOne() | ||
- | </code> | ||
- | |||
- | * Dacă se dorește întoarcerea unui număr ''n'' de documente se folosește **limit(n)** | ||
- | <code javascript> | ||
- | db.students.find().limit(3) | ||
- | </code> | ||
- | |||
- | * Dacă se dorește sortarea rezultatelor după valoare unui anumit câmp se folosește ''sort({label_1: order, label_2: order,..., label_n:order})'' unde ''order'' este ''1'' pentru ascendent și ''-1'' pentru descendent. | ||
- | |||
- | <code javascript> | ||
- | db.students.find().sort({"grupa": 1}) | ||
- | </code> | ||
- | |||
- | * Dacă se dorește afișarea într-un mod citibil în consolă se folosește **pretty()** | ||
- | <code javascript> | ||
- | db.students.find().pretty() | ||
- | </code> | ||
- | |||
- | * **pretty**, **limit** și **sort** se pot folosi împreună | ||
- | |||
- | <code javascript> | ||
- | db.students.find().sort({"student.firstname": 1}).limit(3).pretty() | ||
- | </code> | ||
- | |||
- | </note> | ||
- | |||
- | <color red>Ex. 6.</color> Să se selecteze primele 4 rezultate ale unei cereri care întoarce toți studenți ordonați descrescător după nume. | ||
- | |||
- | |||
- | === Filtrarea cererilor === | ||
- | |||
- | Pentru a filtra rezultatele se folosește parametru **query**. | ||
- | |||
- | Pentru comparație avem: | ||
- | |||
- | * '':'' - egalitate | ||
- | * ''$ne'' - diferit de (not equal) | ||
- | * ''$gt'' - mai mare | ||
- | * ''$gte'' - mai mare sau egal | ||
- | * ''$lt'' - mai mic | ||
- | * ''$lte'' - mai mic sau egal | ||
- | * ''$in'' - căutare într-o listă | ||
- | * ''$all'' - căutare cu egalitate pe toate elementele dintr-o listă | ||
- | |||
- | |||
- | <code javascript> | ||
- | db.students.find({"student.firstname": "Ion"}) | ||
- | db.students.find({an: {$gte: 4}}) | ||
- | db.students.find({"materii.nume": {$in: ['SCAD', 'IA']} }) | ||
- | db.students.find({"grupa": /^341/ }) | ||
- | db.students.find({"cunostinte": {$all: [/^J/, /^C/ ]}}) | ||
- | </code> | ||
- | |||
- | Operatori logici | ||
- | * ''$or'' - sau logic | ||
- | * ''$and'' - și logic | ||
- | * ''$not'' - negare logic | ||
- | |||
- | |||
- | <code javascript> | ||
- | db.students.find({$or: [{"student.lastname": "Ionescu"}, {"cunostinte": /^C/}]}) | ||
- | db.students.find({$and: [{"student.lastname": "Ionescu"}, {"cunostinte": /^C/}]}) | ||
- | </code> | ||
- | |||
- | Operatori utili pentru vectori | ||
- | * ''$size'' pentru a verifica dimensiune | ||
- | * ''0, 1, 2,...'' pentru poziționare (indexare vectorilor începe de la 0) | ||
- | |||
- | |||
- | <code javascript> | ||
- | db.students.find({"cunostinte": {$size: 2}}) | ||
- | db.students.find({"cunostinte.2": "SQL"}) | ||
- | db.students.find({"materii.0.nume": "BD2"}) | ||
- | </code> | ||
- | |||
- | Pentru a verifica existența unui câmp se folosește ''$exists'' | ||
- | <code javascript> | ||
- | db.students.find({"sef": true}) | ||
- | db.students.find({"sef": {$exists: true}}) | ||
- | db.students.find({"sef": false}) | ||
- | db.students.find({"sef": {$exists: false}}) | ||
- | </code> | ||
- | |||
- | |||
- | <note important>Acești operatori pot să fie folosiți împreună.</note> | ||
- | |||
- | <color red>Ex. 7.</color> Explicați ce fac cererile din acest subcapitol. | ||
- | |||
- | <color red>Ex. 8.</color> Să se selecteze toți studenții din anul 4 care au restanțe și știu limbajele de programare C și SQL. | ||
- | |||
- | === Proiecția === | ||
- | |||
- | Pentru a proiecta doar anumite câmpuri se se folosește parametrul **projection**. | ||
- | În cazul în care nu se folosește filtrare se pun acolade fără goale pentru **query**. | ||
- | |||
- | <code javascript> | ||
- | db.students.find({}, {"student.firstname": 1}) | ||
- | </code> | ||
- | |||
- | O cerere cu **projection** va întoarce doar câmpurile specificate și ''_id''. Dacă se dorește să se elimine câmpul ''_id'' atunci proiecția trebuie să conțină și ''"_id": 0'' | ||
- | |||
- | <code javascript> | ||
- | db.students.find({}, {"_id": 0, "student.firstname": 1}) | ||
- | </code> | ||
- | |||
- | <color red>Ex. 9.</color> Să se selecteze studenții care nu sunt șefi și au cunoștințe de "Python" pe a doua poziție din vectorul de cunoștințe. Afișați doar numele, prenumele și vectorul de cunoștințe. | ||
- | |||
- | ==== Modificarea datelor ==== | ||
- | |||
- | Pentru a modifica datele se poate folosi una din comenzile: | ||
- | * ''db.collection.update(<query>, <update>, <options>)'' ([[https://docs.mongodb.com/manual/reference/method/db.collection.update/|Documentație]]) | ||
- | |||
- | Unde: | ||
- | * ''query'' - filtrează datele | ||
- | * ''update'' - setează date care trebuie modificate | ||
- | * ''options'' - diferite opțiuni, e.g.: | ||
- | * ''upsert: <boolean>'' - crează un nou document în cazul în care nu se găsește nici un document cu filtrul | ||
- | * ''multi: <boolean>'' - modifică mai multe documente | ||
- | |||
- | Pentru a seta o valoare se folosește ''$set'': | ||
- | <code javascript> | ||
- | db.students.update({"student.firstname": "George"}, {$set: {"grupa": "342C1"}}) | ||
- | db.students.update({an: 4, "student.firstname": "Grigore"}, {$set: {cunostinte: ["C++"]}}) | ||
- | </code> | ||
- | |||
- | Folosind ''$set'' se suprascrie valoarea pentru câmp. În cazul în care dorim sa modificăm o structură de tip vector folosiți ''$push''. Dacă se dorește să se adauge mai multe valori, se poate folosi ''$push'' împreună cu ''$each''. | ||
- | <code javascript> | ||
- | db.students.update({an: 4, "student.firstname": "Grigore"}, {$push: {"cunostinte": "C"}}) | ||
- | db.students.update({an: 4, "student.firstname": "Grigore"}, {$push: {"cunostinte":{$each: ["Python", "SQL", "Ruby"]}}}) | ||
- | </code> | ||
- | |||
- | Dacă se dorește să se modifice valoare unui element dintr-o listă sau a unui câmp dintr-un document imbricat care se găsește în listă se poate folosi ''$''. Trebuie să selectați și valoare/câmpul care se dorește să fie modificat în ''query'': | ||
- | <code javascript> | ||
- | db.students.update({"student.firstname": "Grigore", "cunostinte": "C"}, {$set: {"cunostinte.$": "Java"}}) | ||
- | db.students.update({"student.firstname": "Grigore", "materii.nume": "SRIC"}, {$set: {"materii.$.nume": "SPG"}}) | ||
- | db.students.update({"student.firstname": "Grigore", "materii.nume": "SPG"}, {$set: {"materii.$.nume": "SRIC", "materii.$.an":4}}) | ||
- | </code> | ||
- | |||
- | <color red>Ex. 10.</color> Să se adauge la toți studenți de anul 3 materiile EGC și LFA (nume si an) folosind o singură comandă. | ||
- | |||
- | |||
- | |||
- | Alte funcții care modifică datele sunt: | ||
- | * ''db.collection.updateOne(<query>, <update>, <options>)'' | ||
- | * ''db.collection.updateMany(<query>, <update>, <options>)'' | ||
- | * ''db.collection.updateMany(<query>, <update>, <options>)'' | ||
- | |||
- | |||
- | ==== Ștergerea datelor ==== | ||
- | Pentru a șterge un document dintr-o colecție se folosește comanda: | ||
- | * ''db.collection.remove(<query>, <justOne>)'' [[https://docs.mongodb.com/manual/reference/method/db.collection.remove/|Documentație]] | ||
- | |||
- | Unde | ||
- | * ''query'' - filtrează datele | ||
- | * ''justOne'' - boolean pentru a șterge unul (''true'') sau mai multe (''false'' -- implicit) documente | ||
- | |||
- | <code javascript> | ||
- | db.students.remove({"an": {$lt: 4}}) | ||
- | </code> | ||
- | |||
- | <note important> | ||
- | Pentru a șterge toate documentele se folosește ''db.collection.remove({})'' | ||
- | <code javascript> | ||
- | db.students.remove({}) | ||
- | </code> | ||
- | </note> | ||
- | |||
- | Alte comenzi care pot fi utilizare pentru a șterge documente dintr-o colecție sunt: | ||
- | * ''db.collection.deleteOne(<filter>)'' | ||
- | * ''db.collection.deleteMany(<filter>)'' | ||
- | |||
- | <color red> Ex. 11.</color> Să se șteargă doar un student care are materia BD2. | ||
- | |||