Introducció
Les bases de dades documental emmagatzemen dades com a documents.
Document
A continuació tens un exemple d'un document JSON que descriu al empleat Laura
:
{
"_id": "laura",
"firstName": "Laura",
"lastName": "Codina",
"email": "laura@acme.com",
"department": "Finance"
}
Els documents de les bases de dades documental són autodescriptius , el que significa que contenen tant els valors de les dades com la informació sobre quin tipus de dades s'emmagatzemen.
A continuació tens un document d'un altre empleat que treballa en diversos departaments:
{
"_id": "roser",
"firstName": "Roser",
"lastName": "Vilalta",
"email": "roser@acme.com",
"salary": 70000,
"department": ["Finance", "Accounting"]
}
Aquest segon document té algunes diferències respecte al primer exemple.
A les bases de dades documentals, els documents no només es descriuen per si mateixos, sinó que també el seu esquema és dinàmic, la qual cosa significa que no cal definir-lo abans de començar a desar les dades. Els camps poden diferir entre diferents documents de la mateixa base de dades, i pots modificar l'estructura del document a voluntat, afegint o eliminant camps a mesura que avances. Els documents també es poden imbricar, és a dir, un camp d'un document pot tenir un valor que consisteix en un altre document, cosa que permet emmagatzemar dades complexes dins d'una única entrada de document.
{
"_id": "david",
"firstName": "David",
"lastName": "de Mingo",
"email": "david@acme.com",
"department": ["Finance", "Accounting"],
"socialMediaAccounts": [
{
"type": "facebook",
"username": "david_de_mingo"
},
{
"type": "twitter",
"username": "@ddemingo"
}
]
}
Entorn de treball
Instal.la MongoDB i el MongoDB Shell:
> scoop install main/mongodb extras/mongosh
Arrenca la base de dades:
> start-process -NoNewWindow mongodb.exe
Executa el shell:
> mongosh
Current Mongosh Log ID: 6780f879bf517fb2d4cb0ce1
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.3.8
Using MongoDB: 8.0.4
Using Mongosh: 2.3.8
...
test>
El shell es connecta al desplegament de MongoDB que s'executa a localhost amb el port predeterminat 27017.
Això és equivalent a l'ordre següent:
> mongosh "mongodb://localhost:27017"
Pots verificar la teva connexió de base de dades actual utilitzant el mètode db.getMongo()
.
test> db.getMongo()
mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.3.8
El mètode retorna l'URI de l'string de connexió per a la teva connexió actual:
Bases de dades, col.leccions i documents
MongoDB emmagatzema la seva informació en documents, que es poden mostrar en format JSON (JavaScript Object Notation). Probablement us agradaria emmagatzemar diferents tipus de documents, com ara usuaris i comandes, en llocs separats. Això vol dir que MongoDB necessita una manera d'agrupar documents, de manera similar a una taula en un base de dades relacional. A MongoDB, això s'anomena col·lecció.
MongoDB divideix les col·leccions en bases de dades separades. A diferència de la sobrecàrrega habitual que produeixen les bases de dades al món SQL, les bases de dades de MongoDB són només espais de noms per distingir entre col·leccions. Per consultar MongoDB, haureu de conèixer la base de dades (o l'espai de noms) i la col·lecció que voleu consultar per als documents. Si no s'especifica cap altra base de dades a l'inici, el shell selecciona una base de dades per defecte anomenada test.
Per mostrar la base de dades que utilitzeu, escriu db
:
> db
test
L'operació hauria de retornar test
, que és la base de dades per defecte.
A continuació crea una base de dades nova per mantenir tots els exercicis de l'activitat en el mateix espai de noms:
test> use demo
switched to db demo
demo>
Veureu un missatge que verifica que heu canviat de base de dades.
És hora de crear el vostre primer document. Com que utilitzeu un shell de JavaScript, els vostres documents s'especificaran en JSON. Per exemple, un document senzill que descrigui un usuari podria semblar així:
{ name: "laura" }
El document conté una única clau i un valor per emmagatzemar el nom d'usuari de la Laura.
Insercions i consultes
Per desar aquest document, heu de triar una col·lecció on desar-lo. Prou adequadament, el desaràs a la col·lecció users
.
demo> db.users.insertOne({name: "laura"})
{
acknowledged: true,
insertedId: ObjectId('678171de72c54e457acb0ce2')
}
Si no existeix una col·lecció, MongoDB la crea la primera vegada que emmagatzemeu les dades d'aquesta col·lecció.
Si la inserció té èxit, acabeu de desar el vostre primer document.
Podeu fer una consulta per veure el nou document:
demo> db.users.find()
[ { _id: ObjectId('678171de72c54e457acb0ce2'), name: 'laura' } ]
Tanca la connexió amb exit
o quit
.
demo> exit
Torna a l'altre terminal para la base de dades MongoDB, i torna a arrencar la base de dades.
Torna a connectar-te a la base de dades.
Com que les dades ara formen part de la col·lecció users
, tornar a obrir l'intèrpret d'ordres i executar la consulta mostrarà el mateix resultat:
test> use demo
switched to db demo
demo> db.users.find()
[ { _id: ObjectId('678171de72c54e457acb0ce2'), name: 'laura' } ]
_ID FIELDS
Tingueu en compte que s'ha afegit un camp _id
al document. Podeu pensar en el valor _id
com a clau primària del document. Cada document de MongoDB requereix un _
id, i si no n'hi ha cap quan es crea el document, es generarà un ObjectID
i s'afegirà al document en aquest moment.
L'ObjectID
que apareix al teu shell no serà el mateix que el de la llista de codi, però serà únic entre tots els valors _id
de la col·lecció, que és l'únic requisit per al camp. Podeu establir el vostre propi _id
establint-lo al document que inseriu, l'ObjectID
és només el predeterminat de MongoDB
Afegeix un nou usuari a la col.lecció:
demo> db.users.insertOne({name: "david"})
{
acknowledged: true,
insertedId: ObjectId('6781722272c54e457acb0ce3')
}
Ara hi hauria d'haver dos documents a la col·lecció. Continueu i comproveu-ho executant l'ordre count
:
demo> db.users.countDocuments()
2
Predicat de consulta
Ara que teniu més d'un document a la col·lecció, mirem algunes consultes una mica més sofisticades. Com abans, encara podeu consultar tots els documents de la col·lecció:
demo> db.users.find()
[
{ _id: ObjectId('678171de72c54e457acb0ce2'), name: 'laura' },
{ _id: ObjectId('6781722272c54e457acb0ce3'), name: 'david' }
]
També podeu passar un senzill selector de consultes al mètode find
. Un selector de consultes és un document que s'utilitza per fer coincidir tots els documents de la col·lecció. Per consultar tots els documents on el nom d'usuari és laura
, passeu un document senzill que actua com a selector de consultes com aquest:
demo> db.users.find({name:"laura"})
[ { _id: ObjectId('678171de72c54e457acb0ce2'), name: 'laura' } ]
El predicat de consulta {username: "laura"}
retorna tots els documents on username
és laura
.
Tingueu en compte que cridar el mètode find
sense cap argument és equivalent a passar un predicat buit: db.users.find()
és el mateix que db.users.find({})
.
A continuació, afegeix alguns usuaris més amb insertMany
:
demo> db.users.insertMany([
... {name:"laura", age: 34},
... {name:"roser", email: "roser@gmail.com"}
... ])
{
acknowledged: true,
insertedIds: {
'0': ObjectId('678172be72c54e457acb0ce4'),
'1': ObjectId('678172be72c54e457acb0ce5')
}
}
El shell de MongoDB afegeix els tres punts després de la primera línia de la consulta per indicar que l'ordre pren més d'una línia.
També pots especificar diversos camps al predicat de consulta, que crea un AND
implícit entre els camps.
Per exemple, consulteu amb el selector següent:
demo> db.users.find({name:"laura", age:34})
[
{ _id: ObjectId('678172be72c54e457acb0ce4'), name: 'laura', age: 34 }
]
La consulta torna tots els documents en que name
és igual a "laura" i age
és igual a 34.
També pots utilitzar l'operador $and
de manera explícita. La consulta anterior és idèntica a:
demo> db.users.find({ $and: [{name:"laura",age:34}] })
[
{ _id: ObjectId('678172be72c54e457acb0ce4'), name: 'laura', age: 34 }
]
La selecció de documents amb un OR
és similar: només cal que utilitzeu l'operador $or
.
Considereu la consulta següent:
demo> db.users.find({ $or: [ {name: "david"}, {age: 34} ] })
[
{ _id: ObjectId('6781722272c54e457acb0ce3'), name: 'david' },
{ _id: ObjectId('678172be72c54e457acb0ce4'), name: 'laura', age: 34 }
]
La consulta retorna els documents david i laura, perquè hem demanat un nom david
o una edat de 34.
Aquest exemple és diferent dels anteriors, perquè no només insereix o cerca un document concret. Més aviat, la consulta en si és un document. La idea de representar les ordres com a documents s'utilitza sovint a MongoDB i pot sorprendre si esteu acostumats a les bases de dades relacionals. Un dels avantatges d'aquesta interfície és que és més fàcil crear consultes amb programació a la vostra aplicació perquè són documents en lloc d'una string SQL llarg.
Actualitzar un documents
Totes les actualitzacions requereixen almenys dos arguments. El primer especifica quins documents cal actualitzar i el segon defineix com s'han de modificar els documents seleccionats. Els primers exemples mostren la modificació d'un sol document, però les mateixes operacions es poden aplicar a molts documents, fins i tot a una col·lecció sencera, tal com mostrem al final d'aquesta secció. Però tingueu en compte que per defecte el mètode update()
actualitza un sol document.
Hi ha dos tipus generals d'actualitzacions, amb propietats i casos d'ús diferents. Un tipus d'actualització implica aplicar operacions de modificació a un document o documents, i l'altre tipus implica substituir el document antic per un de nou.
Modificar
El primer tipus d'actualització implica passar un document amb algun tipus de descripció de l'operador com a segon argument a la funció d'actualització.
En aquesta secció, veureu un exemple de com utilitzar l'operador $set
, que estableix un sol camp amb el valor especificat.
Suposem que l'usuari David decideix afegir el seu país de residència.
Amb updateOne
pots modificar un document:
demo> db.users.updateOne({name:"david"}, {$set: {country: "Spain"}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
Aquesta actualització indica a MongoDB que trobi un document on el nom d'usuari sigui "david" i que, a continuació, estableixi el valor de la propietat del country
a Spain
. Veu que el canvi es reflecteix al missatge que el servidor envia de tornada (modifiedCount: 1
).
Si ara fas una consulta, pots veure que el document s'ha actualitzat:
demo> db.users.find({name:"david"})
[
{
_id: ObjectId('6781722272c54e457acb0ce3'),
name: 'david',
country: 'Spain'
}
]
A continuació actualitzem el pais de residencia de la laura:
demo> db.users.updateOne({name:"laura"}, {$set: {country: "Spain"}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
demo> db.users.find({name:"laura"})
[
{
_id: ObjectId('678171de72c54e457acb0ce2'),
name: 'laura',
country: 'Spain'
},
{ _id: ObjectId('678172be72c54e457acb0ce4'), name: 'laura', age: 34 }
]
El mètode updateOne
només actuatliza el primer document que troba.
Si tornes a repetir l'operació pots veure que no passa res:
demo> db.users.updateOne({name:"laura"}, {$set: {country: "Spain"}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 0,
upsertedCount: 0
}
Pots veure que s'ha trobat un document matchedCount: 1
, però que no s'ha modificat modifiedCount: 0
.
Si vols actualitzar totes les laures a la vegada ho pots fer amb el mètode updateMany
, però enlloc d'això actuatlitazarem només la laura que té 34 anys:
demo> db.users.updateOne({name:"laura", age: 34}, {$set: {country: "Spain"}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
demo> db.users.find({name:"laura"})
[
{
_id: ObjectId('678171de72c54e457acb0ce2'),
name: 'laura',
country: 'Spain'
},
{
_id: ObjectId('678172be72c54e457acb0ce4'),
name: 'laura',
age: 34,
country: 'Spain'
}
]
Dades complexes
Els documents poden contenir estructures de dades complexes.
Suposem que, a més d'emmagatzemar la informació del perfil, els usuaris poden emmagatzemar llistes de les seves coses preferides.
Un exemple de document podria ser aquest:
{
name: "roser",
favorites: {
cities: ["Barcelona", "Girona"],
movies: ["Forrest Gump", "The Godfather", "Titanic"]
}
}
La clau favorites
apunta a un objecte que conté dues claus més, que apunten a llistes de ciutats i pel·lícules preferides. Tenint en compte el que ja sabeu, podeu pensar en una manera de modificar el document original de la roser?
demo> db.users.updateOne({name: "roser"}, {$set: {
... favorites: {
... cities: ["Barcelona","Girona"],
... movies: ["Forrest Gump", "The Godfather", "Titanic"]
... }}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
Tingueu en compte que l'ús de l'espaiat per al sagnat no és obligatori, però ajuda a evitar errors, ja que el document és més llegible d'aquesta manera.
Modific david
de la mateixa manera, però en aquest cas només afegireu un parell de pel·lícules preferides:
demo> db.users.updateOne({ name: "david" }, { $set: { favorites: { movies: ["Forrest Gump", "Life of Brian"] }}})
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
Si cometeu una errada, podeu utilitzar la tecla de fletxa amunt per recordar l'última declaració de l'intèrpret d'ordres.
Ara consulteu la col·lecció users
per assegurar-vos que ambdues actualitzacions han tingut èxit:
demo> db.users.find()
[
...
{
_id: ObjectId('678172be72c54e457acb0ce5'),
name: 'roser',
email: 'roser@gmail.com',
favorites: {
cities: [ 'Barcelona', 'Girona' ],
movies: [ 'Forrest Gump', 'The Godfather', 'Titanic' ]
}
}
]
En sentit estricte, el mètode find()
retorna un cursor als documents que retornen. Per tant, per accedir als documents haureu d'iterarel cursor. El mètode find()
retorna automàticament 20 documents (si estan disponibles) després d'iterar el cursor 20 vegades.
A continució consulta tots el usuaris als qui els hi agrada la pel.lícula Forrest Gump:
demo> db.users.find({"favorites.movies": "Forrest Gump"})
[
{
_id: ObjectId('6781722272c54e457acb0ce3'),
name: 'david',
country: 'Spain',
favorites: { movies: [ 'Forrest Gump', 'Life of Brian' ] }
},
{
_id: ObjectId('678172be72c54e457acb0ce5'),
name: 'roser',
email: 'roser@gmail.com',
favorites: {
cities: [ 'Barcelona', 'Girona' ],
movies: [ 'Forrest Gump', 'The Godfather', 'Titanic' ]
}
}
]
El punt entre favorites
i movies
indica al motor de consultes que cerqui una clau anomenada favorites
que apunti a un objecte amb una clau interna anomenada movies
i després que coincideixi amb el valor de la clau interna. Per tant, aquesta consulta retornarà els dos documents d'usuari perquè les consultes a les llistes coincideixen si algun element de la llista coincideix amb la consulta original
Add to set
Suposem que sabeu que a qualsevol usuari que li agradi Forrest Gump també li agrada Pulp Ficton i que voleu actualitzar la vostra base de dades per reflectir aquest fet.
Com que tot el que voleu fer és afegir un element a la llista, és millor que utilitzeu $push
o $addToSet
. Els dos operadors afegeixen un element a una llista, però el segon ho fa de manera única, evitant una addició duplicada.
demo> db.users.updateMany( {"favorites.movies": "Forrest Gump"},
... { $addToSet: {"favorites.movies": "Pulp Fiction"}})
{
acknowledged: true,
insertedId: null,
matchedCount: 2,
modifiedCount: 2,
upsertedCount: 0
}
El primer argument és un predicat de consulta que coincideix amb els usuaris que tenen Forrest Gump a la seva llista de pel·lícules. El segon argument afegeix Pulp Fiction a aquesta llista mitjançant l'operador $addToSet
.
Esborrant dades
Per eliminar només un determinat subconjunt dels documents d'una col·lecció pots passar un selector de consultes al mètode remove().
Si vola eliminar tots els usuaris la ciutat preferida dels quals és Girona, l'expressió és senzilla:
demo> db.users.deleteOne({"favorites.cities": "Barcelona"})
{ acknowledged: true, deletedCount: 1 }
Si vols eliminar tots els documents d'una col.lecció:
demo> db.users.deleteMany({})
{ acknowledged: true, deletedCount: 3 }
Tingues en compte que l'operació deleteMany({})
en realitat no elimina la col·lecció; només elimina documents d'una col·lecció.
Si la vostra intenció és suprimir la col·lecció juntament amb tots els seus índexs, utilitzeu el mètode drop()
:
demo> db.users.drop()
true
Altres característiques del shell
És possible que ja ho hàgiu notat, però le shell fa moltes coses per facilitar el treball amb MongoDB. Podeu tornar a visitar les ordres anteriors fent servir les fletxes amunt i avall i utilitzar l'emplenament automàtic per a determinades entrades, com ara els noms de les col·leccions. La funció d'emplenament automàtic utilitza la tecla de tabulació per emplenar automàticament o per llistar les possibilitats de finalització.
També podeu descobrir més informació a l'intèrpret d'ordres escrivint això:
> help
Moltes funcions imprimeixen missatges d'ajuda que també els expliquen. Prova-ho:
demo> db.help()
Database Class:
getMongo Returns the current database connection
getName Returns the name of the DB
...
demo> db.getName()
demo
També hi ha diverses opcions que podeu utilitzar quan inicieu l'intèrpret d'ordres de MongoDB. Per mostrar una llista d'aquests, afegiu el flag d'ajuda al arrencar el shell:
> mongo --help
Índexs
És habitual crear índexs per millorar el rendiment de les consultes. Afortunadament, els índexs de MongoDB es poden crear fàcilment des del shell.
Un exemple d'indexació només té sentit si teniu una col·lecció amb molts documents.
Per tant, afegireu 20.000 documents senzills a una col·lecció de números. Com que el shell de MongoDB també és un intèrpret de JavaScript, el codi per aconseguir-ho és senzill:
demo> for (i=0; i < 20000; i++) { db.numbers.insertOne({num:i}) }
{
acknowledged: true,
insertedId: ObjectId('6782894472c54e457acb5b06')
}
Són molts documents, així que no us sorpreneu si la inserció triga uns quants segons a completar-se. Un cop torni, podeu executar un parell de consultes per verificar que tots els documents estan presents:
demo> db.numbers.countDocuments()
20000
demo> db.numbers.find()
[
{ _id: ObjectId('6782893c72c54e457acb0ce7'), num: 0 },
{ _id: ObjectId('6782893c72c54e457acb0ce8'), num: 1 },
{ _id: ObjectId('6782893c72c54e457acb0ce9'), num: 2 },
{ _id: ObjectId('6782893c72c54e457acb0cea'), num: 3 },
{ _id: ObjectId('6782893c72c54e457acb0ceb'), num: 4 },
{ _id: ObjectId('6782893c72c54e457acb0cec'), num: 5 },
{ _id: ObjectId('6782893c72c54e457acb0ced'), num: 6 },
{ _id: ObjectId('6782893c72c54e457acb0cee'), num: 7 },
{ _id: ObjectId('6782893c72c54e457acb0cef'), num: 8 },
{ _id: ObjectId('6782893c72c54e457acb0cf0'), num: 9 },
{ _id: ObjectId('6782893c72c54e457acb0cf1'), num: 10 },
{ _id: ObjectId('6782893c72c54e457acb0cf2'), num: 11 },
{ _id: ObjectId('6782893c72c54e457acb0cf3'), num: 12 },
{ _id: ObjectId('6782893c72c54e457acb0cf4'), num: 13 },
{ _id: ObjectId('6782893c72c54e457acb0cf5'), num: 14 },
{ _id: ObjectId('6782893c72c54e457acb0cf6'), num: 15 },
{ _id: ObjectId('6782893c72c54e457acb0cf7'), num: 16 },
{ _id: ObjectId('6782893c72c54e457acb0cf8'), num: 17 },
{ _id: ObjectId('6782893c72c54e457acb0cf9'), num: 18 },
{ _id: ObjectId('6782893c72c54e457acb0cfa'), num: 19 }
]
Type "it" for more
El mètode countDocuments()
mostra que heu inserit 20.000 documents. La consulta posterior mostra els primers 20 resultats (aquest número pot ser diferent al vostre shell).
Podeu mostrar resultats addicionals amb la funció it:
demo> it
[
{ _id: ObjectId('6782893c72c54e457acb0cfb'), num: 20 },
{ _id: ObjectId('6782893c72c54e457acb0cfc'), num: 21 },
...
La funció it
indica al shell que retorni el següent conjunt de resultats.
A continuació fes una consulta:
demo> db.numbers.find({num:500})
[ { _id: ObjectId('6782893c72c54e457acb0edb'), num: 500 } ]
Intervals
També pots fet consultes d'interval mitjançant els operadors especials $gt
i $lt
que representen major que i menys que, respectivament.
A continuació consulta tots els documents amb un valor numérico superior a 19995:
demo> db.numbers.find({num: {"$gt": 19995}})
[
{ _id: ObjectId('6782894472c54e457acb5b03'), num: 19996 },
{ _id: ObjectId('6782894472c54e457acb5b04'), num: 19997 },
{ _id: ObjectId('6782894472c54e457acb5b05'), num: 19998 },
{ _id: ObjectId('6782894472c54e457acb5b06'), num: 19999 }
]
També pots combinar els dos operadors per especificar els límits superior i inferior:
demo> db.numbers.find({num: {$gt: 20, $lt: 25}})
[
{ _id: ObjectId('6782893c72c54e457acb0cfc'), num: 21 },
{ _id: ObjectId('6782893c72c54e457acb0cfd'), num: 22 },
{ _id: ObjectId('6782893c72c54e457acb0cfe'), num: 23 },
{ _id: ObjectId('6782893c72c54e457acb0cff'), num: 24 }
]
Podeu veure que utilitzant un document JSON senzill, podeu especificar una consulta d'interval de la mateixa manera que ho faríeu a SQL. $gt
i $lt
són només dos d'una sèrie d'operadors que integren el llenguatge de consulta MongoDB. Altres inclouen $gte
per a major o igual a, $lte
per (ho heu endevinat) menor o igual a i $ne
per no igual a.
Per descomptat, consultes com aquesta tenen poc valor tret que també siguin eficients:
Explain
Quan una base de dades rep una consulta, ha de planificar com executar-la; això s'anomena pla de consultes.
explain
descriu els camins de consulta i permet als desenvolupadors diagnosticar operacions lentes determinant quins índexs ha utilitzat una consulta. Sovint, una consulta es pot executar de diverses maneres i, de vegades, això provoca un comportament que potser no espereu.
demo> db.numbers.find({num: {"$gt": 19995}}).explain("executionStats")
{
explainVersion: '1',
queryPlanner: {
namespace: 'demo.numbers',
parsedQuery: { num: { '$gt': 19995 } },
...
executionStats: {
executionSuccess: true,
nReturned: 4,
executionTimeMillis: 4,
totalKeysExamined: 0,
totalDocsExamined: 20000,
La paraula clau "executionStats" sol·licita un mode diferent que ofereix una sortida més detallada:
Després d'examinar la sortida d'explain()
, us sorprendrà veure que el motor de consultes ha d'escanejar tota la col·lecció, els 20.000 documents (totalDocsExamined
), per retornar només quatre resultats (nReturned
). El valor del camp totalKeysExamined
mostra el nombre d'entrades d'índex escanejades, que és zero. Una diferència tan gran entre el nombre de documents escanejats i el nombre retornat marca això com una consulta ineficient.
En una situació del món real, on la col·lecció i els mateixos documents probablement serien més grans, el temps necessari per processar la consulta seria substancialment més gran que els 4 mil·lisegons (`executionTimeInMillis) indicats aquí (això pot ser diferent a la vostra màquina).
El que necessita aquesta col·lecció és un índex. Podeu crear un índex per a la clau num
dels documents mitjançant el mètode createIndex()
:
demo> db.numbers.createIndex({num: 1})
num_1
Pots verure que passes un document al mètode createIndex()
per definir les claus de l'índex. En aquest cas, el document {num: 1}
indica que s'ha de crear un índex ascendent a la clau num
per a tots els documents de la col·lecció numbers
.
Pots verificar que l'índex s'ha creat invocant al mètode getIndexes()
:
demo> db.numbers.getIndexes()
[
{ v: 2, key: { _id: 1 }, name: '_id_' },
{ v: 2, key: { num: 1 }, name: 'num_1' }
]
La col·lecció té ara dos índexs. El primer és l'índex estàndard _id
que es crea automàticament per a cada col·lecció; el segon és l'índex que heu creat a num
. Els índexs d'aquests camps s'anomenen _id
i num_1
, respectivament. Si no proporcioneu un nom, MongoDB estableix automàticament noms significatius.
Si executeu la vostra consulta amb el mètode explain()
, ara veureu la gran diferència en el temps de resposta de la consulta, tal com es mostra a la llista següent:
demo> db.numbers.find({num: {"$gt": 19995}}).explain("executionStats")
{
...
executionStats: {
executionSuccess: true,
nReturned: 4,
executionTimeMillis: 1,
totalKeysExamined: 4,
totalDocsExamined: 4,
...
Ara que la consulta utilitza l'índex num_1
a num
, només escaneja els quatre documents relacionats amb la consulta. Això redueix el temps total per atendre la consulta de 4 ms a 1 ms!
Els índexs no són gratuïts; ocupen una mica d'espai i poden fer que les vostres insercions siguin una mica més cares, però són una eina essencial per a l'optimització de consultes.
Administració
Informació de la base de dades
Sovint voldreu saber quines col·leccions i bases de dades existeixen en una instal·lació determinada. Afortunadament, l'intèrpret d'ordres de MongoDB proporciona una sèrie d'ordres, juntament amb una mica de sucre sintàctic, per obtenir informació sobre el sistema.
show dbs
imprimeix una llista de totes les bases de dades del sistema:
demo> show dbs
admin 40.00 KiB
config 108.00 KiB
demo 672.00 KiB
local 72.00 KiB
show collections
mostra una llista de totes les col·leccions definides a la base de dades actual.
demo> show collections
numbers
Per obtenir una visió de nivell inferior sobre bases de dades i col·leccions, el mètode stats()
resulta útil. Quan l'executeu en un objecte de base de dades, obtindreu la següent sortida:
demo> db.stats()
{
db: 'demo',
collections: Long('1'),
views: Long('0'),
objects: Long('20000'),
avgObjSize: 31,
dataSize: 620000,
storageSize: 237568,
indexes: Long('2'),
indexSize: 409600,
totalSize: 647168,
scaleFactor: Long('1'),
fsUsedSize: 317962870784,
fsTotalSize: 510735151104,
ok: 1
}
També podeu executar l'ordre stats()
en una col·lecció individual:
demo> db.numbers.stats()
{
ok: 1,
capped: false,
Alguns dels valors proporcionats en aquests documents de resultats només són útils en situacions complicades de depuració o d'ajust. Però, com a mínim, podreu esbrinar quant d'espai ocupa una col·lecció determinada i els seus índexs.
Compass
Compass és una eina interactiva per consultar, optimitzar i analitzar les vostres dades de MongoDB.
Instal.la:
> scoop install extras/mongodb-compass
Dades de mostra
Descarrega el conjunt de dades de mostra complet:
> curl https://atlas-education.s3.amazonaws.com/sampledata.archive -o sampledata.archive
Instal.la les eines d'administració:
> scoop install main/mongodb-database-tools
Executa mongorestore
per desempaquetar i allotjar una còpia local del conjunt de dades de mostra (la base de dades ha d'estar arrencada):
> mongorestore --archive=sampledata.archive
> rm .\sampledata.archive