Un CRUD (Create,Read,Update,Delete) pueden ser las operaciones generales que puede realizar un sistema para el manejo de datos. Depende de el entorno de desarrollo puede variar la manera en la que se implementa.
En MongoDB es posible implementar estas funcionalidades a través de sus diferentes métodos, sin embargo primero es necesario conocer algunos comandos generales de la Mongo Shell una vez estemos conectados a nuestro cluster.
Este comando nos muestra todas las bases de datos que se han creado en nuestro cluster
show dbs
use database_name
Cabe aclarar que MongoDB no crea bases de datos vacías, si se quiere que la base de datos se materialice se le debe de crear un documento.
Si queremos saber los métodos que podemos ejecutar sobre alguna entidad de mongo como lo puede ser la base de datos o las colecciones, debemos invocar al método help()
//Muestra todas las funciones que podemos hacer a la base de datos en uso
db.help()
//Muestra todas las funciones que le podemos hacer a una colección
db.collectionName()
Esto se pude realizar a través del comando insertOne()
en la shell de mongo. Al momento de ejecutarlo el comando nos regresara si se creo o no el documento
db.collectionName.insertOne({
// Document in JSON format
})
<h3>Ejemplo</h3>
En este caso insertamos un objeto JSON con ciertos atributos a la colección inventory
db.inventory.insertOne({
item:"canvas",
qty:100,
tags:["cotton"],
size: {
h:28,
w:35.5,
uom:"cm"}
})
La respuesta si se crea correctamente es un JSON con el siguiente formato
{
"acknowledged" : true,
"insertedId" : ObjectId("5cf9b8caaeeb19e36bd25af5")
}
Donde el ObjectId es un identificador único que recibe ese documento, si nosotros no lo especificamos Mongo lo asignara automáticamente. Es obligatorio que exista ese campo en todos los documentos, el valor de este campo jamas se debe repetir en los documentos.
MongoDB tiene algo llamado atomicidad dentro de los documentos, quiere decir que cuando se realiza una operación de escritura esta debe ser atómica. Es decir que si no se llega a completar de manera correcta se realiza la operación de rollback, que es que el documento no se guarde dentro de la base de datos. Esto nos garantiza que la operación no se realice de forma parcial, como podría ser el escribir en el documento solo un campo aunque los demas tengan errores.
MongoDB nos da la opción de poder insertar diferentes documentos en la base de datos enviando un arreglo de objetos a través de la función insertMany()
. La sintaxis se puede ver de la siguiente forma.
db.collectionName.insertMany([
{
...Document1
},{
...Document2
}])
<h3>Ejemplo</h3>
En el siguiente bloque de código se puede ver como agregamos un arreglo de objetos a la colección inventory
db.inventory.insertMany( [
{ item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
{ item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
{ item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }] )
Si todos nuestros documentos se agregaron de la manera adecuada sin que sucediera un rollback, de respuesta podemos esperar por MongoDB un arreglo de objetos confirmándonos que se crearon correctamente devolviéndonos el _id de cada uno
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5cfd49c9edbc9424e14849a9"),
ObjectId("5cfd49c9edbc9424e14849aa"),
ObjectId("5cfd49c9edbc9424e14849ab"),
ObjectId("5cfd49c9edbc9424e14849ac"),
ObjectId("5cfd49c9edbc9424e14849ad"),
ObjectId("5cfd49c9edbc9424e14849ae"),
ObjectId("5cfd49c9edbc9424e14849af"),
ObjectId("5cfd49c9edbc9424e14849b0"),
ObjectId("5cfd49c9edbc9424e14849b1"),
ObjectId("5cfd49c9edbc9424e14849b2")
]
}
En Mongo existen diferentes formas de buscar los documentos, podemos hacerlo a través de filtros o directamente por el objectId. Para esto se utilizan dos métodos, find()
y findOne()
.
find()
Nos regresa uno o mas documentos que cumplan con ciertas condiciones que especifiquemos, si no especificamos ninguna condición de búsqueda nos regresara todos los documentos de la colección.
//buscamos el documento con _id que sea igual a 5cfd49c9edbc9424e14849ae//Como el id es único solo nos regresara un documento
db.inventory.find("5cfd49c9edbc9424e14849ae")
//Nos regresara todos los documentos donde el item sea igual a "canvas"
db.inventory.find({item: "canvas"})
findOne()
Nos regresa solo un documento que cumpla con ciertas condiciones, si no especificamos ninguna condición de búsqueda nos regresara el ultimo documento registrado en la colección.
//buscamos el documento con _id que sea igual a 5cfd49c9edbc9424e14849ae//Como el id es único solo nos regresara un documento
db.inventory.find("5cfd49c9edbc9424e14849ae")
//Nos regresara el ultimo documento donde el item sea igual a "canvas"
db.inventory.find({item: "canvas"})
Como se puede observar existen muchísimas formas de poder buscar un documento gracias a los filtros. Algo interesante de recordar es que los documentos que se almacenan en MongoDB no se almacenan en forma de JSON, si no de BSON. Por lo que algunas veces cuando realicemos búsquedas hay que tener en cuenta esto.
Por ejemplo si nosotros realizamos la búsqueda de un documento a través de su ObjectId con un filtro de la siguiente manera.
db.inventory.findOne({_id: 'quieroBuscarEsteObjectId'})
Nos regresara null
debido a que el objectId no es parte de la especificación de JSON (basicamente son incompatibles). Para esto usamos el método ObjectId()
para realizar la búsqueda. La forma de usarlo la puedes ver en el siguiente ejemplo
db.inventory.findOne({_id: ObjectId('quieroBuscarEsteObjectId')})
Algo importante de los querys en Mongo, es que en los filtros que hacemos podemos buscar mas de un parametro, y podemos implementar algo muy util en Mongo que son los Query and Projection Operators, que son operadores que nos ayudan a que se cumplan condiciones especificas dentro de los parametros de nuestro query. Estos son denotados con el simbolo de dolar $
Algunos ejemplos de estos operadores son
Operador | |
---|---|
$eq | Encuentra los valores que son iguales al valor de búsqueda |
$gt | Encuentra los valores que son mayores al valor de búsqueda |
$gte | Encuentra los valores que son mayores o iguales al valor de búsqueda |
$in | Encuentra cualquiera de los valores que coinciden con los elementos del array de búsqueda. |
$lt | Encuentra los valores que son menores al valor de búsqueda |
$lte | Encuentra los valores que son menores o iguales al valor de búsqueda. |
$ne | Encuentra los valores que no son iguales al valor de búsqueda. |
$nin | Encuentra cualquiera de los valores que no coinciden con los elementos del array de búsqueda. |
Encuentra todos los documentos que tengan un estatus ‘A’ y que su cantidad sea menor a ‘30’ (lower than)
db.inventory.find( { status: "A", qty: { $lt: 30 } } )
Como en todo CRUD es necesario realizar la operacion de Actualizar (UPDATE), para eso Mongo se vale de los métodos updateOne()
y updateMany()
que análogamente funcionan de manera similar que findOne()
y find()
.
La gran diferencia aquí consta en los parámetros que reciben estas funciones que actualizaran nuestros documentos. La estructura es la siguiente
db.collectionName.updateOne(<filter>, <update>)
En el argumento de <filter>
debe de ir la condición con la cual nosotros decidiremos que documentos actualizar, por ejemplo un filtro valido podría ser el objectId u otro podría ser todos los documentos que tuvieran una cantidad de piezas menor a 40.
En el argumento de update ira los campos que deseemos actualizar, pueden ser uno o varios los campos que podemos actualizar. Estos campos deben de ir después del operador $set
Si queremos actualizar la cantidad de un solo producto que cumpla con el filtro, entonces podemos usar updateOne()
. En este ejemplo actualizaremos el primer producto que tenga una cantidad mayor a 10 en el inventario y le colocaremos una status “B”
db.inventory.updateOne({ qty: { $gt: 10 } },{ $set: { status: "B" } })
//Solo actualiza el primero que encuentre en el orden natural //de registro en disco
En dado caso que quisiéramos que se actualizaran todos los productos con esa condición del filtro se utilizaría updateMany()
db.inventory.updateOne({ qty: { $gt: 10 } },{ $set: { status: "B" } })
//Actualizaria todos los que cumplan la condicion del filtro
Es importante saber que el método update()
, updateOne()
y updateMany()
pueden recibir un tercer parámetro que sirven como opciones para saber que puede hacer el update bajo ciertos comportamientos. Todas estas opciones se pueden profundizar en la documentación de MongoDB.
Una de las opciones mas interesantes que tiene el update es la de upsert
, si nosotros activamos este parámetro la actualización se puede comportar como un insert en caso de que el filtro no se cumpla.
Imaginemos que hacemos una actualización por id en nuestra colección, pero resulta que el id no existe. Si no activamos la opcion de upsert
lo valores que pasamos para actualizar no tendrán ningún efecto en la base de datos. Sin embargo si elupsert
esta activo Mongo creara un nuevo documento con esos datos.
db.inventory.update(
{ _id: "id_que_no_existe"},
{ $set: { qty: 40 } },
{ upsert: true }
)
Con la opción de upsert
activa mongo nos creara un documento con el siguiente formato
{ "_id" : "algunID", "qty" : 40 }
Al igual que los otros métodos dentro de Mongo, existe el deleteOne()
y deleteMany()
. Estos se comportan de manera muy similar a que findOne()
y find()
. Solo que al momento de cumplir con la condición del filtro estos métodos eliminaran al documento.
//Elimina solo el primer documento que encuentre con el criterio del filtro
db.collectionName.deleteOne(filter)
//Elimina todos los documentos que encuentre con el criterio del filtro
db.collectionName.deleteMany(filter)
Como sabemos las operaciones de lectura no son riesgosas para los datos que tengamos almacenados en nuestra base de datos. Sin embargo las operaciones de escritura, actualización y eliminación de documentos pueden ser demasiado riesgosas si no se hacen bien.
Aqui hay algunas recomendaciones que se pueden seguir para no comprometer nuestros datos al hacer estas operaciones
find()
y verificar que documentos nos regresa.upsert
al momento de actualizar, es recomendable que lo que actualicemos sea un esquema general de nuestro documento. Aunque MongoDB no maneja esquemas, a veces es bueno implementarlos para tener una mejor organización de nuestros datos.
Tengo unas observaciones como por hacer feedback:
De resto todo bien muchas gracias por el resumen
Muchas gracias por la retroalimentación 😄
Muchas gracias @edevars, estaba perdido con esta clase, y con esta guía resolví varias dudas
No hay de que, un gusto el poderte haber ayudado 😊
Gracias por la información, muy buen resumen.
Hay algo a mejorar respecto al metodo findOne(), la documentación nos dice lo siguiente:
Returns one document that satisfies the specified query criteria on the collection or view. If multiple documents satisfy the query, this method returns the first document according to the natural order which reflects the order of documents on the disk. In capped collections, natural order is the same as insertion order. If no document satisfies the query, the method returns null.
$eq =
$gt >
$gte >=
$lt <
$lte <=
$ne !=
$in valores dentro de un rango
$nin valores que no estan dentro de un rango
$and Une queries con un AND logico
$not Invierte el efecto de un query
$nor Une queries con un NOR logico
$or Une queries con un OR logico
$exist Docuemntos que cuentan con un campo especifico
$type Docuemntos que cuentan con un campo de un tipo especifico
$all Arreglos que contengan todos los elementos del query
$elemMatch Documentos que cumplen la condicion del $elemMatch en uno de sus elementos
$size Documentos que contienen un campo tipo arreglo de un tamaño especifico.
Genial aporte.
Es muy práctico tu instructivo, resuelve a mayor detalle varias dudas que se quedan al aire en el video.
Muchas gracias por el aporte. Definitivamente esto me llevó a comprender muchas cosas.
Gracias!