Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tutosrive/db-nosql-2026-1/llms.txt

Use this file to discover all available pages before exploring further.

El script mongo.py del repositorio genera grandes volúmenes de datos sintéticos de usuarios (hasta 50 millones de registros por defecto) para usar en pruebas de rendimiento y ejercicios con MongoDB. Usa la librería Faker y el patrón generador de Python (yield) para minimizar el uso de RAM, escribiendo los documentos línea por línea en un archivo JSONL que luego se importa a MongoDB con mongoimport.

Requisitos

El script requiere solo una dependencia:
requirements.txt
faker==40.19.1
Instala las dependencias con:
pip install -r requirements.txt
O directamente:
pip install faker==40.19.1

El Script Completo

mongo.py
import json
import os
import random as rd
from datetime import datetime
from faker import Faker

fk = Faker()
TOTAL_RECORDS = 50_000_000
OUTPUT_FILE = "./data/users.jsonl"

os.makedirs("./data", exist_ok=True)

def user_generator():
    """Generador que crea un usuario a la vez (ahorra RAM)."""
    countries = ["US", "DK", "FR", "ES", "BR", "CA", "DE"]

    for i in range(1, TOTAL_RECORDS + 1):
        male = i % 2 == 0
        gender = "male" if male else "female"
        first_name = fk.first_name_male() if male else fk.first_name_female()
        last_name = fk.last_name()
        pic_id = rd.randint(1, 99)
        gender_path = "men" if male else "women"

        yield {
            "gender": gender,
            "name": {
                "title": "mr" if male else "ms",
                "first": first_name.lower(),
                "last": last_name.lower(),
            },
            "location": {
                "street": f"{rd.randint(100, 9999)} {fk.street_name().lower()}",
                "city": fk.city().lower(),
                "state": fk.state().lower(),
                "postcode": rd.randint(10000, 99999),
                "coordinates": {
                    "latitude": f"{rd.uniform(-90, 90):.4f}",
                    "longitude": f"{rd.uniform(-180, 180):.4f}",
                },
                "timezone": {"offset": "+1:00", "description": "Europe/Madrid"},
            },
            "email": f"{first_name.lower()}.{last_name.lower()}@example.com",
            "login": {
                "uuid": fk.uuid4(),
                "username": f"{first_name.lower()}{rd.randint(10,999)}",
                "password": "password123",
                "salt": "salt",
                "md5": "md5hash",
                "sha1": "sha1hash",
                "sha256": "sha256hash",
            },
            "dob": {"date": "1990-01-01T00:00:00Z", "age": 36},
            "registered": {"date": "2020-01-01T00:00:00Z", "age": 6},
            "phone": "123-4567",
            "cell": "987-6543",
            "id": {"name": "DNI", "value": f"{rd.randint(100000,999999)}"},
            "picture": {
                "large": f"https://randomuser.me/api/portraits/{gender_path}/{pic_id}.jpg",
                "medium": f"https://randomuser.me/api/portraits/med/{gender_path}/{pic_id}.jpg",
                "thumbnail": f"https://randomuser.me/api/portraits/thumb/{gender_path}/{pic_id}.jpg",
            },
            "nat": rd.choice(countries),
        }


with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
    for count, user in enumerate(user_generator(), 1):
        f.write(json.dumps(user, ensure_ascii=False) + "\n")

        if count % 500_000 == 0:
            print(f"Guardados {count:,} usuarios...")

Cómo Ejecutar el Script

1

Instalar dependencias

Desde el directorio Scripts/generate-fake-users/:
pip install faker==40.19.1
2

Ejecutar el script

python mongo.py
El script imprime el progreso cada 500.000 registros:
Guardados 500,000 usuarios...
Guardados 1,000,000 usuarios...
Guardados 1,500,000 usuarios...
3

Verificar el archivo de salida

El archivo se escribe en ./data/users.jsonl. Puedes ver las primeras líneas para confirmar el formato:
head -3 ./data/users.jsonl
Generar 50 millones de registros tomará varias horas y ocupará aproximadamente 25–30 GB de espacio en disco. Para pruebas locales, reduce TOTAL_RECORDS a un valor menor (ver sección Personalizar el Script).

Estructura del Documento Generado

Cada línea del archivo JSONL es un documento JSON independiente con la siguiente estructura:
{
  "gender": "male",
  "name": {
    "title": "mr",
    "first": "carlos",
    "last": "rodríguez"
  },
  "location": {
    "street": "1234 maple avenue",
    "city": "springfield",
    "state": "illinois",
    "postcode": 62701,
    "coordinates": {
      "latitude": "39.7817",
      "longitude": "-89.6501"
    },
    "timezone": {
      "offset": "+1:00",
      "description": "Europe/Madrid"
    }
  },
  "email": "carlos.rodriguez@example.com",
  "login": {
    "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "username": "carlos247",
    "password": "password123"
  },
  "dob": { "date": "1990-01-01T00:00:00Z", "age": 36 },
  "registered": { "date": "2020-01-01T00:00:00Z", "age": 6 },
  "phone": "123-4567",
  "cell": "987-6543",
  "id": { "name": "DNI", "value": "456789" },
  "picture": {
    "large": "https://randomuser.me/api/portraits/men/42.jpg",
    "medium": "https://randomuser.me/api/portraits/med/men/42.jpg",
    "thumbnail": "https://randomuser.me/api/portraits/thumb/men/42.jpg"
  },
  "nat": "US"
}
Los campos clave que se usan en los ejercicios del curso son:
CampoTipoDescripción
genderString"male" o "female" (alterna por índice)
name.first / name.lastStringNombre generado con Faker (en minúsculas)
location.city / location.stateStringCiudad y estado generados con Faker
dob.ageNumberFijo en 36 (actualizable con el ejercicio de fechas)
natStringCódigo de país elegido aleatoriamente de: US, DK, FR, ES, BR, CA, DE
El formato JSONL (JSON Lines) es diferente de un array JSON estándar. Cada línea es un documento JSON válido e independiente, sin comas entre documentos y sin corchetes [] envolventes. mongoimport puede leer este formato sin la bandera --jsonArray.

Importar a MongoDB

Una vez generado el archivo, impórtalo con mongoimport:
# Sin --jsonArray porque el archivo es JSONL (un documento por línea)
mongoimport \
  --db dbpersonas \
  --collection personas \
  --file ./data/users.jsonl
Verifica que la importación fue correcta:
use dbpersonas
db.personas.countDocuments()
db.personas.findOne({})

Personalizar el Script

Puedes modificar dos constantes al inicio del script:
TOTAL_RECORDS = 50_000_000  # Cambia este número
OUTPUT_FILE = "./data/users.jsonl"  # Cambia la ruta de salida
Para pruebas locales rápidas usa TOTAL_RECORDS = 100_000 (100 mil registros). Esto genera un archivo de ~80 MB en menos de un minuto y es suficiente para practicar todas las agregaciones del curso.
También puedes ajustar los países disponibles en la lista countries dentro de la función user_generator():
countries = ["US", "DK", "FR", "ES", "BR", "CA", "DE"]
# Agrega o quita países según tus necesidades de prueba

Patrón Generador — Por qué usa yield

El script usa un generador de Python (yield) en lugar de construir una lista con todos los usuarios en memoria. La razón es simple: no es posible cargar 50 millones de objetos Python en RAM simultáneamente.
def user_generator():
    """Generador: crea un usuario a la vez (ahorra RAM)."""
    for i in range(1, TOTAL_RECORDS + 1):
        # yield entrega un usuario y PAUSA la función
        # hasta que el bucle externo pida el siguiente
        yield { ... }

# El bucle externo consume de a uno, escribiendo inmediatamente
with open(OUTPUT_FILE, "w") as f:
    for count, user in enumerate(user_generator(), 1):
        f.write(json.dumps(user) + "\n")
        # El usuario se descarta de RAM después de escribirse
Con este patrón, el uso de RAM es constante (~unos MB) independientemente de cuántos millones de registros se generen, porque en ningún momento se guarda más de un documento en memoria.

Operadores de Actualización

Aprende a actualizar las edades de la colección personas con $dateDiff

Ejercicios de Agregaciones

Usa la colección personas para practicar pipelines de agregación

Build docs developers (and LLMs) love