MongoDB es una base de datos NoSQL basada en documentos que utiliza un modelo de datos de tipo JSON, en lugar de filas y columnas tradicionales. Es una base de datos de código abierto, de uso sencillo y diseñada para el desarrollo de aplicaciones modernas y para la nube.
JSON/BSONMongoDB almacena los datos en documentos BSON, un formato que extiende JSON para incluir tipos de datos adicionales como fechas, enteros binarios y ObjectIds, proporcionando mayor eficiencia en almacenamiento y consulta.
Ejemplo de documento:
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"name": "Urian",
"edad": 30,
"ciudad": "Bogotá",
"fecha_registro": ISODate("2024-01-15T10:30:00Z"),
"activo": true,
"hobbies": ["programación", "música", "deportes"]
} | NoSQL (MongoDB) | SQL (MySQL, PostgreSQL) |
|---|---|
| Documentos JSON/BSON | Filas y columnas |
| Esquema flexible | Esquema fijo |
| Escalabilidad horizontal | Escalabilidad vertical |
| Consultas con JavaScript | Consultas con SQL |
Un documento es la unidad básica de datos en MongoDB, similar a una fila en una base de datos relacional, pero mucho más flexible. Cada documento puede tener una estructura diferente.
Ejemplo:
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"nombre": "Juan Pérez",
"email": "juan@email.com",
"direccion": {
"calle": "Carrera 15 #85-32",
"ciudad": "Bogotá",
"pais": "Colombia"
}
} Una colección es un grupo de documentos, similar a una tabla en una base de datos relacional. No requiere esquema fijo.
Ejemplo de colección “usuarios”:
// Documento 1
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"nombre": "Juan",
"edad": 25
}
// Documento 2
{
"_id": ObjectId("507f1f77bcf86cd799439012"),
"nombre": "María",
"email": "maria@email.com",
"telefono": "3001234567"
} _id)Cada documento tiene un campo _id único que actúa como clave principal. Si no se proporciona, MongoDB lo genera automáticamente como un ObjectId.
Los índices mejoran significativamente la velocidad de las consultas al crear estructuras de datos optimizadas para búsquedas rápidas.
Las operaciones CRUD (Create, Read, Update, Delete) son fundamentales en MongoDB. A diferencia de SQL, MongoDB utiliza métodos JavaScript para manipular documentos, ofreciendo mayor flexibilidad y una sintaxis más intuitiva para desarrolladores web.
insertOne() - Insertar un solo documentoInserta un único documento en una colección. Si no se especifica un _id, MongoDB lo genera automáticamente. Este método es ideal para operaciones individuales y garantiza la integridad de cada inserción.
Sintaxis: db.coleccion.insertOne(documento)
insertMany() - Insertar múltiples documentosInserta varios documentos en una sola operación, optimizando el rendimiento al reducir las llamadas a la base de datos. Útil para migraciones o carga masiva de datos. Si un documento falla, puedes configurar si continuar con los demás usando la opción ordered: false.
Sintaxis: db.coleccion.insertMany([documento1, documento2, ...])
// ✅ Insertar un documento simple
db.usuarios.insertOne({
"nombre": "Juan Pérez",
"email": "juan@email.com",
"edad": 30,
"ciudad": "Bogotá",
"fecha_registro": new Date()
})
// Respuesta: { acknowledged: true, insertedId: ObjectId("...") }
// ✅ Insertar múltiples documentos de una sola vez (más eficiente)
db.usuarios.insertMany([
{
"nombre": "María García",
"email": "maria@email.com",
"edad": 25,
"ciudad": "Medellín"
},
{
"nombre": "Carlos López",
"email": "carlos@email.com",
"edad": 35,
"ciudad": "Cali"
}
])
// Respuesta: { acknowledged: true, insertedIds: { '0': ObjectId("..."), '1': ObjectId("...") } }
// ✅ Insertar con _id personalizado
db.usuarios.insertOne({
"_id": "USER001",
"nombre": "Admin",
"email": "admin@email.com",
"rol": "administrador"
}) find() - Buscar múltiples documentosRecupera todos los documentos que coincidan con los criterios de búsqueda. Retorna un cursor que puede iterarse o convertirse en un array. Permite encadenar métodos como sort(), limit() y skip() para controlar los resultados.
Sintaxis: db.coleccion.find(filtro, proyección)
findOne() - Buscar un solo documentoRecupera el primer documento que coincida con los criterios especificados. Es más eficiente que find() cuando solo necesitas un resultado, ya que detiene la búsqueda al encontrar la primera coincidencia.
Sintaxis: db.coleccion.findOne(filtro, proyección)
// ✅ Buscar todos los documentos de la colección
db.usuarios.find()
// ✅ Buscar con un filtro específico
db.usuarios.find({ "ciudad": "Bogotá" })
db.usuarios.find({ "edad": 30 })
// ✅ Buscar con múltiples condiciones (AND implícito)
db.usuarios.find({
"edad": { $gte: 25 },
"ciudad": "Bogotá"
})
// ✅ Buscar un solo documento (más rápido)
db.usuarios.findOne({ "email": "juan@email.com" })
// ✅ Proyección: seleccionar solo campos específicos
// 1 = incluir, 0 = excluir
db.usuarios.find({}, { "nombre": 1, "email": 1, "_id": 0 })
// ✅ Ordenar resultados
db.usuarios.find().sort({ "edad": 1 }) // Ascendente (1)
db.usuarios.find().sort({ "edad": -1 }) // Descendente (-1)
db.usuarios.find().sort({ "ciudad": 1, "edad": -1 }) // Múltiples campos
// ✅ Limitar número de resultados
db.usuarios.find().limit(5)
// ✅ Paginación: saltar y limitar documentos
db.usuarios.find().skip(10).limit(5) // Página 3 (si cada página tiene 5 elementos)
// ✅ Encadenar múltiples operaciones
db.usuarios.find({ "edad": { $gte: 18 } })
.sort({ "nombre": 1 })
.limit(10)
.skip(0)
// ✅ Buscar y convertir a array
db.usuarios.find({ "ciudad": "Bogotá" }).toArray()
// ✅ Contar documentos que coinciden con el filtro
db.usuarios.find({ "ciudad": "Bogotá" }).count() Los operadores de comparación permiten filtrar documentos basándose en condiciones numéricas o de igualdad (similares a las cláusulas WHERE en SQL).
| Operador | Significado | Ejemplo | Resultado |
|---|---|---|---|
$eq | Igual a | { edad: { $eq: 25 } } | edad = 25 |
$ne | Distinto de | { edad: { $ne: 18 } } | edad ≠ 18 |
$gt | Mayor que | { precio: { $gt: 100 } } | precio > 100 |
$gte | Mayor o igual que | { precio: { $gte: 100 } } | precio ≥ 100 |
$lt | Menor que | { precio: { $lt: 50 } } | precio < 50 |
$lte | Menor o igual que | { precio: { $lte: 50 } } | precio ≤ 50 |
$in | Coincide con alguno en un array | { categoria: { $in: ["tecnología", "hogar"] } } | categoria ∈ [“tecnología”,“hogar”] |
$nin | No coincide con ninguno | { categoria: { $nin: ["ropa", "deporte"] } } | categoria ∉ [“ropa”,“deporte”] |
Permiten combinar múltiples condiciones en una sola consulta usando lógica booleana (AND, OR, NOT, NOR).
| Operador | Descripción | Ejemplo |
|---|---|---|
$and | Todas las condiciones deben cumplirse | { $and: [ { precio: { $gt: 100 } }, { stock: { $gte: 5 } } ] } |
$or | Cualquiera de las condiciones puede cumplirse | { $or: [ { categoria: "hogar" }, { categoria: "oficina" } ] } |
$not | Niega una condición | { precio: { $not: { $gt: 500 } } } → precio ≤ 500 |
$nor | Ninguna condición debe cumplirse | { $nor: [ { activo: true }, { premium: true } ] } |
Verifican la existencia o el tipo de dato de un campo específico en los documentos.
| Operador | Descripción | Ejemplo |
|---|---|---|
$exists | Verifica si el campo existe | { descuento: { $exists: true } } |
$type | Filtra por tipo de dato | { edad: { $type: "int" } } |
Permiten realizar consultas avanzadas sobre campos que contienen arrays, evaluando elementos, tamaño y coincidencias.
| Operador | Descripción | Ejemplo |
|---|---|---|
$all | Todos los valores deben estar en el array | { tags: { $all: ["nuevo", "oferta"] } } |
$elemMatch | Coincidencia en un elemento del array | { puntuaciones: { $elemMatch: { $gte: 80, $lt: 100 } } } |
$size | Tamaño exacto del array | { colores: { $size: 3 } } |
Evalúan expresiones complejas y patrones de texto usando expresiones regulares o comparaciones entre campos.
| Operador | Descripción | Ejemplo |
|---|---|---|
$regex | Coincidencia con expresión regular | { nombre: { $regex: /^A/i } } → nombres que empiecen con “A” |
$expr | Usa expresiones dentro de la consulta | { $expr: { $gt: ["$ventas", "$gastos"] } } |
// ✅ Operadores de Comparación
db.usuarios.find({ "edad": { $gt: 25 } }) // Mayor que 25
db.usuarios.find({ "edad": { $gte: 25 } }) // Mayor o igual a 25
db.usuarios.find({ "edad": { $lt: 30 } }) // Menor que 30
db.usuarios.find({ "edad": { $lte: 30 } }) // Menor o igual a 30
db.usuarios.find({ "edad": { $ne: 25 } }) // Diferente de 25
db.usuarios.find({ "edad": { $eq: 25 } }) // Igual a 25
db.usuarios.find({ "ciudad": { $in: ["Bogotá", "Medellín", "Cali"] } }) // Está en el array
db.usuarios.find({ "ciudad": { $nin: ["Bogotá", "Medellín"] } }) // No está en el array
// ✅ Operadores Lógicos
db.usuarios.find({
$or: [
{ "ciudad": "Bogotá" },
{ "ciudad": "Medellín" }
]
})
db.usuarios.find({
$and: [
{ "edad": { $gte: 25 } },
{ "ciudad": "Bogotá" }
]
})
db.usuarios.find({
$nor: [
{ "activo": false },
{ "bloqueado": true }
]
})
// ✅ Operadores para Arrays
db.usuarios.find({ "hobbies": "programación" }) // Contiene el elemento
db.usuarios.find({ "hobbies": { $in: ["música", "deportes"] } }) // Contiene al menos uno
db.usuarios.find({ "hobbies": { $all: ["música", "deportes"] } }) // Contiene todos
db.usuarios.find({ "hobbies": { $size: 3 } }) // Array con exactamente 3 elementos
// ✅ Búsqueda con Expresiones Regulares (Regex)
db.usuarios.find({ "nombre": /Juan/ }) // Contiene "Juan"
db.usuarios.find({ "nombre": { $regex: "^Juan" } }) // Empieza con "Juan"
db.usuarios.find({ "nombre": { $regex: "Pérez$" } }) // Termina con "Pérez"
db.usuarios.find({ "nombre": { $regex: "juan", $options: "i" } }) // Case insensitive
// ✅ Operadores de Existencia
db.usuarios.find({ "telefono": { $exists: true } }) // Tiene el campo telefono
db.usuarios.find({ "telefono": { $exists: false } }) // No tiene el campo telefono
// ✅ Operadores de Tipo
db.usuarios.find({ "edad": { $type: "int" } }) // El campo es un entero
db.usuarios.find({ "edad": { $type: "string" } }) // El campo es un string
// ✅ Consultas Complejas Combinadas
db.usuarios.find({
$and: [
{ "edad": { $gte: 18, $lte: 65 } },
{ "ciudad": { $in: ["Bogotá", "Medellín"] } },
{ "activo": true },
{ "email": { $exists: true } }
]
}) updateOne() - Actualizar un documentoModifica el primer documento que coincida con el filtro especificado. Usa operadores como $set, $inc, $push, $pull para realizar cambios precisos sin reemplazar todo el documento.
Sintaxis: db.coleccion.updateOne(filtro, actualización, opciones)
updateMany() - Actualizar múltiples documentosModifica todos los documentos que coincidan con el filtro. Ideal para actualizaciones masivas como cambiar estados, incrementar valores o agregar campos a múltiples registros simultáneamente.
Sintaxis: db.coleccion.updateMany(filtro, actualización, opciones)
replaceOne() - Reemplazar documento completoReemplaza completamente un documento por uno nuevo, manteniendo solo el _id original. A diferencia de updateOne(), elimina todos los campos no especificados en el nuevo documento.
Sintaxis: db.coleccion.replaceOne(filtro, nuevoDocumento, opciones)
// ✅ $set - Actualizar o agregar campos
db.usuarios.updateOne(
{ "email": "juan@email.com" },
{ $set: { "edad": 31, "ciudad": "Medellín", "activo": true } }
)
// ✅ updateMany - Actualizar múltiples documentos
db.usuarios.updateMany(
{ "ciudad": "Bogotá" },
{ $set: { "pais": "Colombia", "zona": "Andina" } }
)
// ✅ $inc - Incrementar o decrementar valores numéricos
db.usuarios.updateOne(
{ "email": "juan@email.com" },
{ $inc: { "edad": 1, "puntos": 10 } } // edad +1, puntos +10
)
db.productos.updateOne(
{ "_id": "PROD001" },
{ $inc: { "stock": -5 } } // Restar 5 del stock
)
// ✅ $push - Agregar elementos a un array
db.usuarios.updateOne(
{ "email": "juan@email.com" },
{ $push: { "hobbies": "lectura" } }
)
// ✅ $push con $each - Agregar múltiples elementos
db.usuarios.updateOne(
{ "email": "juan@email.com" },
{ $push: { "hobbies": { $each: ["fotografía", "cocina"] } } }
)
// ✅ $pull - Remover elementos de un array
db.usuarios.updateOne(
{ "email": "juan@email.com" },
{ $pull: { "hobbies": "música" } }
)
// ✅ $unset - Eliminar campos del documento
db.usuarios.updateOne(
{ "email": "juan@email.com" },
{ $unset: { "telefono": "", "direccion": "" } }
)
// ✅ $rename - Renombrar campos
db.usuarios.updateMany(
{},
{ $rename: { "nombre": "nombre_completo" } }
)
// ✅ $mul - Multiplicar valor de un campo
db.productos.updateOne(
{ "_id": "PROD001" },
{ $mul: { "precio": 1.15 } } // Aumentar precio 15%
)
// ✅ $min y $max - Actualizar solo si es menor/mayor
db.estadisticas.updateOne(
{ "usuario_id": "USER001" },
{
$min: { "puntuacion_minima": 50 }, // Solo actualiza si 50 es menor
$max: { "puntuacion_maxima": 100 } // Solo actualiza si 100 es mayor
}
)
// ✅ replaceOne - Reemplazar documento completo (mantiene solo _id)
db.usuarios.replaceOne(
{ "email": "juan@email.com" },
{
"nombre": "Juan Carlos Pérez",
"email": "juan@email.com",
"edad": 31,
"ciudad": "Medellín",
"profesion": "Desarrollador"
}
)
// ✅ upsert - Actualizar o insertar si no existe
db.usuarios.updateOne(
{ "email": "nuevo@email.com" },
{ $set: { "nombre": "Usuario Nuevo", "edad": 25 } },
{ upsert: true } // Crea el documento si no existe
)
// ✅ Actualización compleja combinada
db.usuarios.updateOne(
{ "_id": ObjectId("507f1f77bcf86cd799439011") },
{
$set: { "ultimo_acceso": new Date(), "activo": true },
$inc: { "numero_accesos": 1 },
$push: { "historial": { fecha: new Date(), accion: "login" } }
}
) deleteOne() - Eliminar un documentoElimina el primer documento que coincida con el filtro especificado. Útil cuando necesitas eliminar un registro específico identificado por un criterio único.
Sintaxis: db.coleccion.deleteOne(filtro)
deleteMany() - Eliminar múltiples documentosElimina todos los documentos que coincidan con el filtro. Ideal para limpieza masiva de datos, eliminación de registros obsoletos o depuración. ⚠️ Usa con precaución.
Sintaxis: db.coleccion.deleteMany(filtro)
drop() - Eliminar colección completaElimina completamente una colección incluyendo todos sus documentos e índices. Esta operación es irreversible y libera el espacio de almacenamiento.
Sintaxis: db.coleccion.drop()
// ✅ Eliminar un documento específico
db.usuarios.deleteOne({ "email": "juan@email.com" })
// Respuesta: { acknowledged: true, deletedCount: 1 }
// ✅ Eliminar por _id (más eficiente)
db.usuarios.deleteOne({ "_id": ObjectId("507f1f77bcf86cd799439011") })
// ✅ Eliminar múltiples documentos que cumplan una condición
db.usuarios.deleteMany({ "ciudad": "Bogotá" })
db.usuarios.deleteMany({ "activo": false })
db.usuarios.deleteMany({ "fecha_registro": { $lt: new Date("2020-01-01") } })
// ⚠️ PELIGRO: Eliminar TODOS los documentos de una colección
db.usuarios.deleteMany({}) // Esto borra todo pero mantiene la colección y los índices
// ✅ Eliminar documentos con condiciones complejas
db.usuarios.deleteMany({
$and: [
{ "ultimo_acceso": { $lt: new Date("2023-01-01") } },
{ "activo": false }
]
})
// ✅ Eliminar colección completa (incluye índices)
db.usuarios.drop()
// Respuesta: true (si se eliminó correctamente)
// ✅ Eliminar base de datos completa
db.dropDatabase()
// ✅ Verificar qué se eliminaría antes de borrar (buena práctica)
db.usuarios.find({ "activo": false }).count() // Ver cuántos serían eliminados
db.usuarios.deleteMany({ "activo": false }) // Luego eliminarlos aggregate()El framework de agregación procesa y transforma datos mediante un pipeline (tubería) de operaciones secuenciales. Cada etapa transforma los documentos y los pasa a la siguiente, permitiendo realizar cálculos complejos, agrupaciones, filtrados y transformaciones de datos.
Operadores comunes:
$match: Filtra documentos (similar a WHERE en SQL)$group: Agrupa documentos y realiza operaciones de agregación (similar a GROUP BY)$sort: Ordena los resultados$project: Selecciona qué campos mostrar$limit: Limita el número de documentos$sum, $avg, $min, $max: Operaciones matemáticasSintaxis: db.coleccion.aggregate([etapa1, etapa2, ...])
countDocuments() - Contar documentosCuenta el número de documentos que coinciden con un filtro específico. Más preciso que el método count() obsoleto, ya que cuenta los documentos reales en la colección.
Sintaxis: db.coleccion.countDocuments(filtro)
// ✅ Contar documentos con filtro
db.usuarios.countDocuments({ "ciudad": "Bogotá" })
db.usuarios.countDocuments({ "edad": { $gte: 18 } })
db.usuarios.countDocuments({}) // Contar todos los documentos
// ✅ Agrupación básica con operadores de agregación
db.usuarios.aggregate([
{
$group: {
"_id": "$ciudad", // Agrupar por ciudad
"total": { $sum: 1 }, // Contar documentos
"promedio_edad": { $avg: "$edad" }, // Promedio de edad
"edad_maxima": { $max: "$edad" }, // Edad máxima
"edad_minima": { $min: "$edad" } // Edad mínima
}
}
])
// ✅ Pipeline de agregación completo
db.usuarios.aggregate([
// Etapa 1: Filtrar documentos
{ $match: { "edad": { $gte: 25 }, "activo": true } },
// Etapa 2: Agrupar y calcular estadísticas
{
$group: {
"_id": "$ciudad",
"total_usuarios": { $sum: 1 },
"promedio_edad": { $avg: "$edad" },
"emails": { $push: "$email" } // Crear array con todos los emails
}
},
// Etapa 3: Ordenar resultados
{ $sort: { "total_usuarios": -1 } },
// Etapa 4: Limitar resultados
{ $limit: 10 }
])
// ✅ Agregación con $project (seleccionar campos)
db.usuarios.aggregate([
{
$project: {
"nombre": 1,
"email": 1,
"edad": 1,
"es_mayor": { $gte: ["$edad", 18] }, // Campo calculado
"nombre_mayuscula": { $toUpper: "$nombre" }
}
}
])
// ✅ Agregación con $lookup (JOIN entre colecciones)
db.pedidos.aggregate([
{
$lookup: {
from: "usuarios", // Colección a unir
localField: "usuario_id", // Campo en pedidos
foreignField: "_id", // Campo en usuarios
as: "usuario_info" // Nombre del array resultante
}
}
])
// ✅ Agregación compleja: análisis de ventas
db.ventas.aggregate([
// Filtrar ventas del último año
{ $match: { "fecha": { $gte: new Date("2024-01-01") } } },
// Agrupar por producto y calcular totales
{
$group: {
"_id": "$producto_id",
"total_ventas": { $sum: "$cantidad" },
"ingreso_total": { $sum: { $multiply: ["$precio", "$cantidad"] } },
"venta_promedio": { $avg: "$cantidad" }
}
},
// Ordenar por ingresos (de mayor a menor)
{ $sort: { "ingreso_total": -1 } },
// Tomar los top 5 productos
{ $limit: 5 },
// Formatear resultado final
{
$project: {
"producto_id": "$_id",
"total_ventas": 1,
"ingreso_total": { $round: ["$ingreso_total", 2] },
"venta_promedio": { $round: ["$venta_promedio", 2] },
"_id": 0
}
}
])
// ✅ Agregación con $unwind (descomponer arrays)
db.usuarios.aggregate([
{ $unwind: "$hobbies" }, // Crear un documento por cada hobby
{ $group: { "_id": "$hobbies", "total": { $sum: 1 } } }, // Contar por hobby
{ $sort: { "total": -1 } }
])
// ✅ distinct() - Obtener valores únicos de un campo
db.usuarios.distinct("ciudad") // ["Bogotá", "Medellín", "Cali", ...]
db.productos.distinct("categoria") Los índices son estructuras de datos especiales que mejoran drásticamente la velocidad de las consultas al crear una tabla de búsqueda ordenada. Sin índices, MongoDB debe escanear cada documento (collection scan); con índices, puede saltar directamente a los datos relevantes.
createIndex(campos, opciones): Crea un nuevo índicegetIndexes(): Lista todos los índicesdropIndex(campos): Elimina un índice// ✅ Crear índice simple (1 = ascendente, -1 = descendente)
db.usuarios.createIndex({ "email": 1 })
db.usuarios.createIndex({ "edad": 1 })
// ✅ Crear índice único (no permite valores duplicados)
db.usuarios.createIndex({ "email": 1 }, { unique: true })
db.usuarios.createIndex({ "username": 1 }, { unique: true })
// ✅ Crear índice compuesto (múltiples campos)
// Útil para consultas que filtran por ambos campos
db.usuarios.createIndex({ "ciudad": 1, "edad": 1 })
db.productos.createIndex({ "categoria": 1, "precio": -1 })
// ✅ Crear índice de texto (búsquedas de texto completo)
db.usuarios.createIndex({ "nombre": "text", "biografia": "text" })
db.articulos.createIndex({ "titulo": "text", "contenido": "text" })
// Luego buscar con:
db.usuarios.find({ $text: { $search: "Juan Pérez" } })
// ✅ Crear índice TTL (Time To Live) - elimina documentos automáticamente
// Elimina documentos 30 días después de la fecha especificada
db.sesiones.createIndex(
{ "fecha_expiracion": 1 },
{ expireAfterSeconds: 2592000 } // 30 días = 2,592,000 segundos
)
// ✅ Crear índice parcial (solo indexa documentos que cumplan condición)
db.usuarios.createIndex(
{ "email": 1 },
{ partialFilterExpression: { "activo": true } }
)
// ✅ Crear índice sparse (no indexa documentos sin el campo)
db.usuarios.createIndex(
{ "telefono": 1 },
{ sparse: true }
)
// ✅ Ver todos los índices de una colección
db.usuarios.getIndexes()
// ✅ Ver estadísticas de uso de índices
db.usuarios.aggregate([{ $indexStats: {} }])
// ✅ Eliminar un índice específico
db.usuarios.dropIndex({ "email": 1 })
db.usuarios.dropIndex("email_1") // Por nombre
// ✅ Eliminar todos los índices (excepto _id)
db.usuarios.dropIndexes()
// ✅ Analizar el plan de ejecución de una consulta
db.usuarios.find({ "email": "juan@email.com" }).explain("executionStats")
// Muestra si usa índice, cuántos documentos examinó, tiempo, etc.
// ✅ Crear índice en segundo plano (no bloquea la colección)
db.usuarios.createIndex(
{ "fecha_registro": 1 },
{ background: true }
)
// ✅ Índice geoespacial (para coordenadas y ubicaciones)
db.lugares.createIndex({ "ubicacion": "2dsphere" })
// Luego buscar lugares cercanos:
db.lugares.find({
ubicacion: {
$near: {
$geometry: { type: "Point", coordinates: [-74.0721, 4.7110] }, // Bogotá
$maxDistance: 5000 // 5km
}
}
})
// ✅ Verificar si una colección tiene índices
db.usuarios.getIndexes().length > 1 // true si hay más que el _id Flexibilidad de Esquema
Alto Rendimiento
Ecosistema Rico
Alta Disponibilidad
Escalabilidad