MongoDB es una base de datos NoSQL orientada a documentos: en vez de tablas con filas fijas, guarda JSON (técnicamente BSON) con una estructura flexible, lo que la hace cómoda cuando tus datos no calzan bien en un esquema relacional rígido o cambian seguido. Esta es una guía de referencia con conexión, operaciones CRUD, relaciones entre colecciones, importación de CSV, operadores de consulta, proyecciones y el framework de agregación, con ejemplos reales de mongosh (si corres MongoDB en Docker, el post de comandos esenciales de Docker te sirve para levantar el contenedor).
Conectarse a MongoDB y crear una base de datos y colección
mongosh "mongodb://127.0.0.1:27017" --username user --authenticationDatabase admin
mongosh --host mongodb0.example.com --port 28015
Crear (o cambiar a) una base de datos con use, listar las bases con show dbs y crear una colección simplemente referenciándola:
test> use mibase
mibase> show dbs
admin 100.00 KiB
config 108.00 KiB
local 76.00 KiB
// crear una colección
mibase> db.persona
mibase.persona
// listar las colecciones
mibase> show collections
Insertar documentos
insertOne guarda un solo documento, insertMany guarda varios:
mibase> db.persona.insertOne({"nombres":"Maricel","apellidos":"casanova","edad":25,"sexo":"femenino"})
mibase> db.persona.insertMany([
{"nombres":"Max","apellidos":"casanova","edad":39},
{"nombres":"llasna","apellidos":"gomez","edad":31}
])
mibase> db.plaza.insertOne({
nombre: "plaza2",
precioPantalones: [
{ nombre: "tienda2", valormenor: 100, valormayor: 1000 },
{ nombre: "tienda3", valormenor: 300, valormayor: 2000 }
]
})
mibase> db.plaza.find().pretty()
[
{
_id: ObjectId("64e0065bc68bd53aaff8c599"),
nombre: 'plaza2',
precioPantalones: [
{ nombre: 'tienda2', valormenor: 100, valormayor: 1000 },
{ nombre: 'tienda3', valormenor: 300, valormayor: 2000 }
]
}
]
Otro ejemplo, insertando una película con un arreglo de actores:
mibase> db.peliculas.insertOne({titulo:"el pirata", ano:2021, actores:["max","juan","jose","macarena","isabel"]})
mibase> db.peliculas.find().pretty()
[
{
_id: ObjectId("64e39d5bc68bd53aaff8c5a3"),
titulo: 'el pirata',
ano: 2021,
actores: [ 'max', 'juan', 'jose', 'macarena', 'isabel' ]
}
]
mibase> db.peliculas.insertMany([
{titulo:"hola a todos", ano:1999, actores:["coke","juan"]},
{titulo:"pedrito el lobo", ano:2023, actores:["davis","guillermo",{dato1:"hola",dato2:"chao"}]}
])
insert() también existe (forma antigua, equivalente a insertOne/insertMany según el argumento):
mibase> db.peliculas.insert([{titulo:"peliculas 1", ano:2000},{titulo:"pelicula2", ano:1000}])
Insert ordenado (ordered)
Con {ordered: true}, si un documento falla (por ejemplo por _id duplicado), la operación se detiene y se reporta el error en detalle:
mibase> db.peliculas.insert(
[
{_id: ObjectId("64e39f8fc68bd53aaff8c5a7"), titulo:"prueba 2", ano:2002},
{titulo:"el conquistador", ano:2222}
],
{ordered: true}
)
Uncaught:
MongoBulkWriteError: E11000 duplicate key error collection: mibase.peliculas index: _id_ dup key: { _id: ObjectId('64e39f8fc68bd53aaff8c5a7') }
Result: BulkWriteResult {
insertedCount: 0,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds: {
'0': ObjectId("64e39f8fc68bd53aaff8c5a7"),
'1': ObjectId("64e3a56fc68bd53aaff8c5a8")
}
}
Write Errors: [
WriteError {
err: {
index: 0,
code: 11000,
errmsg: "E11000 duplicate key error collection: mibase.peliculas index: _id_ dup key: { _id: ObjectId('64e39f8fc68bd53aaff8c5a7') }",
op: { _id: ObjectId("64e39f8fc68bd53aaff8c5a7"), titulo: 'prueba 2', ano: 2002 }
}
}
]
Consultas con find y findOne
// mostrar todos los documentos
mibase> db.persona.find()
// mostrar el resultado pero sin el campo _id
mibase> db.persona.find({"edad":25},{"_id":0})
// sin _id ni edad
mibase> db.persona.find({"edad":25},{"_id":0,"edad":0})
// solo el campo "nombres"
mibase> db.persona.find({"sexo":"femenino"},{"nombres":1,"_id":0})
// buscar por _id
mibase> db.persona.find({"_id":ObjectId("64a642bcb7ce53bbb5c28018")})
Cursor:
mibase> db.persona.find().count()
mibase> db.persona.find().limit(3)
Filtrar por tipo de dato:
mibase> db.persona.find({"edad":{$type:"int"}})
mibase> db.persona.find({"nombres":{$type:"string"}})
findOne, y encadenar con una propiedad del resultado:
mibase> db.address.insertOne({"patron_id":"one","street":"serrano 266","city":"santiago","country":"chile"})
mibase> db.address.findOne({patron_id:"one"}).street
serrano 266
mibase> db.persona.findOne({edad:39})
{
_id: ObjectId("64a6351fb7ce53bbb5c28014"),
nombres: 'Kim',
apellidos: 'foxterry',
edad: 39
}
Guardar un resultado en una variable y reutilizarlo:
mibase> db.patron.findOne({"nombre":"Maximiliano Casanova"})._id
one
mibase> var varAuxiliar = db.patron.findOne({"nombre":"Maximiliano Casanova"})._id
mibase> varAuxiliar
one
mibase> db.address.find({patron_id: varAuxiliar})
[
{ _id: ObjectId("64dfa504c68bd53aaff8c595"), patron_id: 'one', street: 'serrano 266', city: 'santiago', country: 'chile' }
]
// o directamente anidado, sin variable intermedia
mibase> db.address.find({patron_id: db.patron.findOne({"nombre":"Maximiliano Casanova"})._id})
mibase> db.address.findOne({patron_id: db.patron.findOne({"nombre":"Maximiliano Casanova"})._id}).city
santiago
// con proyección
mibase> db.address.findOne(
{patron_id: db.patron.findOne({"nombre":"Maximiliano Casanova"})._id},
{city:1, country:1}
)
{ _id: ObjectId("64dfa504c68bd53aaff8c595"), city: 'santiago', country: 'chile' }
Con operadores
Ver la referencia de operadores de MongoDB o la guía de W3Schools.
mibase> db.persona.find({edad:{$gt:39}})
mibase> db.persona.findOne({edad:{$eq:39}})
mibase> db.persona.find({edad:{$lt:39}})
mibase> db.persona.find({edad:{$lte:39}})
Actualizar y reemplazar documentos
replaceOne sustituye el documento completo:
mibase> db.persona.replaceOne(
{"_id":ObjectId("64a642bcb7ce53bbb5c28018")},
{"edad":26,"nombres":"Antonia"}
)
upsert: si {upsert:true}, inserta el documento si no existe; con {upsert:false} (el valor por defecto) no lo inserta:
mibase> db.persona.replaceOne(
{"_id":ObjectId("64a642bcb7ce53bbb5c28018")},
{"edad":26,"nombres":"Antonias","apellido":"Garrido"},
{upsert:false}
)
update / updateOne / updateMany con $set:
// busca por {"nombres":"Kim"} y aplica $set
mibase> db.persona.updateOne({"nombres":"Kim"},{$set:{"apellidos":"perrito","edad":3}},{upsert:true})
// actualizar varios documentos con multi:true
mibase> db.persona.update({"edad":1},{$set:{"apellidos":"canes","edad":39}},{multi:true})
mibase> db.persona.updateMany({"edad":39},{$set:{"apellidos":"foxterry","edad":39}},{multi:true})
Ejemplo agregando un sub-documento address a un cliente:
mibase> db.patron.find()
[ { _id: 'one', nombre: 'Maximiliano Casanova' } ]
mibase> db.patron.updateOne(
{_id:"one"},
{$set:{"address":{"street":"serrano 266","city":"santiago","country":"Chile","depto":"715"}}},
{upsert:true}
)
mibase> db.patron.find()
[
{
_id: 'one',
nombre: 'Maximiliano Casanova',
address: { street: 'serrano 266', city: 'santiago', country: 'Chile', depto: '715' }
}
]
Operadores de actualización ($set, $inc, $min, $max, $mul, $unset, $rename):
mibase> db.peliculas.updateOne({titulo:"actor4"},{$set:{ano:9999}})
mibase> db.peliculas.updateOne({actores:{$in:["juan","coke"]}},{$set:{ano:1010}})
mibase> db.peliculas.updateMany({actores:{$in:["juan","coke"]}},{$set:{ano:101110}})
// $inc suma al valor actual
mibase> db.peliculas.updateOne({actores:{$in:["coke"]}},{$inc:{ano:1}})
// $min solo actualiza si el nuevo valor es menor al actual
mibase> db.peliculas.updateOne({actores:{$in:["coke"]}},{$min:{ano:1}})
// $max solo actualiza si el nuevo valor es mayor al actual
mibase> db.peliculas.updateOne({actores:{$in:["coke"]}},{$max:{ano:2}})
// $mul multiplica el valor actual
mibase> db.peliculas.updateOne({actores:{$in:["coke"]}},{$mul:{ano:2}})
// $unset elimina un campo
mibase> db.peliculas.updateOne({actores:{$in:["coke"]}},{$unset:{"ano":""}})
// $rename cambia el nombre de un campo
mibase> db.peliculas.updateOne({actores:{$in:["coke"]}},{$rename:{"actores":"actores2"}})
Documentos embebidos en arreglos
Cuando un campo contiene un arreglo de sub-documentos:
// estructura de ejemplo
{
_id: 1,
almacen: "almacen1",
inventario: [
{producto:"productoA", in_stock:101},
{producto:"productoB", in_stock:10},
{producto:"productoC", in_stock:30}
]
}
mibase> db.producto.insertMany([{
"item":"prodcutoA",
"stock":[{"seccion":"A","almacen":200},{"seccion":"B","almacen":200},{"seccion":"A","Bodega":1000}]
}])
mibase> db.producto.find()
[
{
_id: ObjectId("64d0471b656e5fd5243faa00"),
item: 'prodcutoA',
stock: [
{ seccion: 'A', almacen: 200 },
{ seccion: 'B', almacen: 200 },
{ seccion: 'A', Bodega: 1000 }
]
}
]
Buscar dentro del arreglo por un campo del sub-documento, o por posición:
mibase> db.producto.find({"stock.seccion":"A"})
mibase> db.producto.find({"stock.0.seccion":"A"})
Eliminar documentos, colecciones y bases de datos
db.miColeccion.drop() // elimina todos los documentos de la colección (y la colección misma)
db.dropDatabase() // elimina la base de datos actual
Tipos de datos en MongoDB
| Tipo | Alias |
|---|---|
| Double | double |
| String | string |
| Object | object |
| Array | array |
| Binary Data | binData |
| Undefined (deprecado) | undefined |
| ObjectId | objectid |
| Boolean | bool |
| Date | date |
| Null | null |
| Regular Expression | regex |
| DBPointer (deprecado) | dbPointer |
| JavaScript | javascript |
| Symbol (deprecado) | symbol |
| JavaScript con scope (deprecado) | javascriptWithScope |
| Entero de 32 bits | int |
| Timestamp | timestamp |
| Entero de 64 bits | long |
| Decimal128 | decimal |
| Min Key | minKey |
| Max Key | maxKey |
Relaciones 1 a 1, 1 a N y N a N
1 a N (una plaza con varios locales, referenciados por id_plaza):
mibase> db.plaza.insertOne({nombre:"plaza1"})
mibase> db.plaza.find().pretty()
[ { _id: ObjectId("64dfffadc68bd53aaff8c597"), nombre: 'plaza1' } ]
mibase> db.pantalon.insertOne({
nombretienda:"tienda1", valorminimo:100, valormaximo:1000,
id_plaza: ObjectId("64dfffadc68bd53aaff8c597")
})
mibase> db.pantalon.insertMany([
{nombre:"tienda2", precio:3000, id_plaza:ObjectId("64e0065bc68bd53aaff8c599")},
{nombre:"tienda3", precio:4500, id_plaza:ObjectId("64e0065bc68bd53aaff8c599")},
{nombre:"tienda4", precio:1200, id_plaza:ObjectId("64e0065bc68bd53aaff8c599")}
])
mibase> db.pantalon.find()
N a N (tiendas y empleados, cada uno referenciando al otro):
mibase> db.tienda.insertMany([
{nombre:"tienda1", direccion:"serrano 266"},
{nombre:"tienda2", direccion:"llano alto 123"}
])
mibase> db.empleado.insertMany([
{nombre:"Max", tienda:[ObjectId("64e0103bc68bd53aaff8c59d"),ObjectId("64e0103bc68bd53aaff8c59e")]},
{nombre:"vale", tienda:[ObjectId("64e0103bc68bd53aaff8c59e")]}
])
mibase> db.empleado.find()
mibase> db.tienda.insertMany([
{nombre:"tienda1", empleado:[ObjectId("64e015c1c68bd53aaff8c59f"),ObjectId("64e015c1c68bd53aaff8c5a0")]},
{nombre:"tienda2", empleado:[ObjectId("64e015c1c68bd53aaff8c5a0")]}
])
Importar un archivo CSV a una colección
Si tu MongoDB corre dentro de un contenedor Docker, el archivo CSV tiene que existir dentro del contenedor antes de poder importarlo — por eso el primer paso es copiarlo con docker cp. Si corres MongoDB directo en tu máquina, puedes saltarte esos dos pasos y ejecutar mongoimport directamente.
Crear el archivo CSV:
titulo,autor,publicacion
"el lobo solitario","maximiliano casanova","2000/02/02"
"papelucho","valeria gome","1989/10/12"
Copiar el archivo dentro del contenedor de MongoDB:
docker cp libro.csv mongodb:/home/compartir
Entrar al contenedor:
docker exec -it mongodb bash
Importar el archivo con mongoimport:
root@54cded7c9e8a:/# mongoimport --db mibase --collection libros --type csv --headerline \
--file libro.csv --username user --authenticationDatabase admin
2023-08-21T19:15:15.386+0000 connected to: mongodb://localhost/
2023-08-21T19:15:15.479+0000 2 document(s) imported successfully. 0 document(s) failed to import.
Y verificar en mongosh:
mibase> db.libros.find()
[
{ _id: ObjectId("64e3b7c3deb40b27a4575685"), titulo: 'papelucho', autor: 'valeria gome', publicacion: '1989/10/12' },
{ _id: ObjectId("64e3b7c3deb40b27a4575686"), titulo: 'el lobo solitario', autor: 'maximiliano casanova', publicacion: '2000/02/02' }
]
Operadores de comparación y lógicos
mibase> db.persona.find({edad:{$gt:39}})
mibase> db.persona.findOne({edad:{$eq:39}})
mibase> db.persona.find({edad:{$lt:39}})
mibase> db.persona.find({edad:{$lte:39}})
mibase> db.persona.find({"edad":{$in:[39,40,43]}})
mibase> db.producto.find({"stock.almacen":{$in:[200,300]}})
mibase> db.persona.find({"edad":{$nin:[39]}})
mibase> db.peliculas.find({$and:[{"ano":{$gte:1999}},{ano:{$lte:2000}}]})
mibase> db.peliculas.find({$or:[{"ano":{$gte:2000}},{ano:2023}]})
mibase> db.peliculas.find({ano:{$not:{$gte:2021}}})
mibase> db.peliculas.find({$nor:[{ano:{$gte:2021}}]})
mibase> db.peliculas.find({actores:{$exists:true}})
mibase> db.peliculas.find({actores:{$exists:false}})
mibase> db.peliculas.find({actores:{$type:"string"}})
Comparación: $eq (igual), $ne (distinto), $gt (mayor), $gte (mayor o igual), $lt (menor), $lte (menor o igual), $in (dentro de un arreglo).
Lógicos: $and, $or, $nor (ninguna coincide), $not (niega la condición).
Evaluación: $regex (expresiones regulares), $text (búsqueda de texto), $where (expresión JavaScript).
Operadores regex, size, all y elemMatch
// expresión regular
mibase> db.peliculas.find({titulo:{$regex:/pelicula/}})
// cantidad exacta de elementos en el arreglo
mibase> db.peliculas.find({"actores":{$size:5}})
mibase> db.peliculas.find({"actores":{$size:2}})
// el arreglo debe contener todos los valores indicados
mibase> db.peliculas.find({"actores":{$all:["juan"]}})
// al menos un elemento del arreglo cumple todas las condiciones
mibase> db.peliculas.find({actores:{$elemMatch:{edad:{$gt:20}}}})
Cursores: sort, skip, limit y next
// guardar el cursor en una variable y recorrerlo manualmente
mibase> const mivar = db.peliculas.find()
mibase> mivar.next()
mibase> mivar.next()
// ordenar ascendente / descendente
mibase> db.peliculas.find().sort({ano:1})
mibase> db.peliculas.find().sort({ano:-1,titulo:1})
// limitar y paginar resultados
mibase> db.peliculas.find().sort({"ano":-1}).limit(2)
mibase> db.peliculas.find().sort({"ano":-1}).limit(2).skip(1)
Proyecciones
mibase> db.persona.find({"edad":25},{"_id":0,"edad":0})
mibase> db.persona.find({"sexo":"femenino"},{"nombres":1,"_id":0})
Proyecciones con matrices ($, $slice)
// el operador $ proyecta solo el elemento del arreglo que hizo match
mibase> db.peliculas.find({actores:"davis"},{"actores.$":1})
[ { _id: ObjectId("64e39ea0c68bd53aaff8c5a5"), actores: [ 'davis' ] } ]
// $slice limita cuántos elementos del arreglo se devuelven
mibase> db.peliculas.find({},{actores:{$slice:2}})
mibase> db.peliculas.find({},{actores:{$slice:1}})
// $slice con [skip, limit]
mibase> db.peliculas.find({},{actores:{$slice:[1,2]},ano:1})
deleteOne, deleteMany y drop
mibase> db.peliculas.deleteOne({actores:{$in:["coke"]}})
{ acknowledged: true, deletedCount: 0 }
mibase> db.peliculas.deleteMany({actores2:{$in:["coke"]}})
{ acknowledged: true, deletedCount: 1 }
// eliminar todos los documentos de la colección
mibase> db.peliculas.deleteMany()
// eliminar la colección completa
mibase> db.peliculas.drop()
// eliminar toda la base de datos
mibase> use mibase
mibase> db.dropDatabase()
Framework de agregación
mibase> db.proyecto.aggregate([
{ $match: { no_cdtos: { $gte: 352 } } }
])
Agrupar y sumar un campo por sucursal:
mibase> db.proyecto.aggregate([
{ $match: { B_adeudo: "Con adeudo" } },
{ $group: { _id: { id_sucursal: "$id_sucursal" }, clienteAdeudo: { $sum: "$no_clientes" } } }
])
Agregar un $sort para ordenar el resultado agrupado:
mibase> db.proyecto.aggregate([
{ $match: { B_adeudo: "Con adeudo" } },
{ $group: { _id: { id_sucursal: "$id_sucursal" }, clienteAdeudo: { $sum: "$no_clientes" } } },
{ $sort: { "clienteAdeudo": -1 } }
])
Y con $project para quedarte solo con ciertos campos, o para calcular un campo nuevo con $concat:
mibase> db.proyecto.aggregate([
{ $match: { B_adeudo: "Con adeudo" } },
{ $group: { _id: { id_sucursal: "$id_sucursal" }, clienteAdeudo: { $sum: "$no_clientes" } } },
{ $sort: { "clienteAdeudo": -1 } },
{ $project: { _id: 0 } }
])
mibase> db.proyecto.aggregate([
{ $match: { B_adeudo: "Con adeudo" } },
{ $group: { _id: { id_sucursal: "$id_sucursal" }, clienteAdeudo: { $sum: "$no_clientes" } } },
{ $sort: { "clienteAdeudo": -1 } },
{
$project: {
_id: 1,
camponuevo: { $concat: ["es un campo ", "nuevo para informar"] }
}
}
])
Con esto cubres las operaciones más comunes de MongoDB: conexión, CRUD completo, relaciones entre colecciones, importación de datos, operadores de consulta, proyecciones y agregación.