# Jakarta NoSQL (MongoDB) en Quarkus: Bases de Datos NoSQL con Dev Services

## **Introducción**

Jakarta NoSQL proporciona una API estándar para trabajar con bases de datos NoSQL. En Quarkus, MongoDB está completamente soportado a través de Panache MongoDB, y **Dev Services** hace que trabajar con MongoDB sea extremadamente simple iniciando automáticamente un contenedor.

## **¿Qué es NoSQL?**

NoSQL (Not Only SQL) se refiere a bases de datos que no usan el modelo relacional tradicional. MongoDB es una base de datos de documentos que almacena datos en formato BSON (Binary JSON), permitiendo estructuras flexibles y complejas.

## **Dev Services: La Magia de Quarkus**

**Dev Services** es una característica de Quarkus que inicia automáticamente servicios necesarios (como MongoDB) en contenedores Docker durante el desarrollo. Esto significa:

* ✅ No necesitas instalar MongoDB manualmente
    
* ✅ No necesitas configurar conexiones
    
* ✅ Solo necesitas Docker instalado
    
* ✅ Quarkus lo hace todo automáticamente
    

```go
# application.properties
quarkus.mongodb.devservices.enabled=true
```

Cuando ejecutas `mvn quarkus:dev`, verás:

```go
Dev Services for MongoDB started.
```

## **Panache MongoDB**

Panache MongoDB proporciona dos patrones similares a Panache para SQL:

### **Active Record Pattern**

```go
@MongoEntity(collection = "heroes")
public class HeroMongo extends PanacheMongoEntity {
    public String name;
    public Integer powerLevel;
    public List<String> abilities = new ArrayList<>();
    
    // Métodos de instancia
    public void activate() {
        this.isActive = true;
        this.update();
    }
    
    // Métodos estáticos
    public static List<HeroMongo> findPowerful(int minLevel) {
        return find("powerLevel >= ?1", minLevel).list();
    }
}
```

### **Repository Pattern**

```go
@ApplicationScoped
public class HeroMongoRepository implements PanacheMongoRepository<HeroMongo> {
    
    public List<HeroMongo> findPowerful(int minPowerLevel) {
        return find("powerLevel >= ?1", minPowerLevel).list();
    }
}
```

## **Características Específicas de MongoDB**

### **1\. Documentos Anidados**

MongoDB permite documentos dentro de documentos:

```go
@MongoEntity(collection = "heroes")
public class HeroMongo extends PanacheMongoEntity {
    public Location location; // Documento anidado
    
    public static class Location {
        public String city;
        public String planet;
        public Coordinates coordinates; // Anidado dentro de anidado
        
        public static class Coordinates {
            public Double latitude;
            public Double longitude;
        }
    }
}
```

### **2\. Arrays de Valores**

```go
public class HeroMongo extends PanacheMongoEntity {
    public List<String> abilities = new ArrayList<>(); // Array de strings
}
```

### **3\. Arrays de Documentos**

```go
public class HeroMongo extends PanacheMongoEntity {
    public List<Mission> missions = new ArrayList<>(); // Array de documentos
    
    public static class Mission {
        public String title;
        public String description;
        public String status;
    }
}
```

### **4\. Queries en Documentos Anidados**

```go
// Buscar por ciudad
public List<HeroMongo> findByCity(String city) {
    return find("location.city", city).list();
}

// Buscar por coordenadas anidadas
public List<HeroMongo> findByLatitude(double lat) {
    return find("location.coordinates.latitude", lat).list();
}
```

### **5\. Queries en Arrays**

```go
// Buscar héroes que tengan una habilidad específica
public List<HeroMongo> findByAbility(String ability) {
    return find("abilities", ability).list();
}

// Buscar héroes con misiones pendientes
public List<HeroMongo> findWithPendingMissions() {
    return find("missions.status", "PENDING").list();
}
```

## **ObjectId vs Long**

MongoDB usa `ObjectId` como identificador en lugar de `Long`:

```go
@MongoEntity(collection = "heroes")
public class HeroMongo extends PanacheMongoEntity {
    // El campo 'id' es de tipo ObjectId (hereda de PanacheMongoEntity)
    // No necesitas declararlo
}

// En los endpoints REST
@GET
@Path("/heroes/{id}")
public Response getHero(@PathParam("id") String id) {
    ObjectId objectId = new ObjectId(id); // Convertir String a ObjectId
    HeroMongo hero = HeroMongo.findById(objectId);
    return Response.ok(hero).build();
}
```

## **Operaciones Comunes**

### **Crear**

```go
HeroMongo hero = new HeroMongo("Superman", "Super strength", 95);
hero.addAbility("Flight");
hero.addAbility("Heat vision");
hero.persist(); // Active Record
```

### **Buscar**

```go
// Por ID
HeroMongo hero = HeroMongo.findById(objectId);

// Por campo
List<HeroMongo> heroes = HeroMongo.find("name", "Superman").list();

// Con condición
List<HeroMongo> powerful = HeroMongo.find("powerLevel >= ?1", 80).list();
```

### **Actualizar**

```go
HeroMongo hero = HeroMongo.findById(objectId);
hero.powerLevel = 98;
hero.addAbility("New ability");
hero.update(); // Active Record
```

### **Eliminar**

```go
HeroMongo.deleteById(objectId);
hero.delete(); // Active Record
```

## **Ejemplo Completo: Estructura Compleja**

```go
HeroMongo superman = new HeroMongo("Superman", "Super strength", 95);
superman.addAbility("Flight");
superman.addAbility("Heat vision");

// Ubicación anidada
HeroMongo.Location location = new HeroMongo.Location();
location.city = "Metropolis";
location.planet = "Earth";
HeroMongo.Location.Coordinates coords = new HeroMongo.Location.Coordinates();
coords.latitude = 40.7128;
coords.longitude = -74.0060;
location.coordinates = coords;
superman.location = location;

// Misiones anidadas
HeroMongo.Mission mission = new HeroMongo.Mission();
mission.title = "Salvar Metropolis";
mission.description = "Detener a Lex Luthor";
mission.status = "COMPLETED";
superman.addMission(mission);

superman.persist();
```

## **Ventajas de MongoDB**

1. **Flexibilidad**: Esquema flexible, documentos pueden variar
    
2. **Estructuras Complejas**: Documentos anidados y arrays nativos
    
3. **Performance**: Mejor para lectura de documentos completos
    
4. **Escalabilidad**: Escala horizontalmente fácilmente
    

## **Comparación: SQL vs NoSQL**

| **Característica** | **SQL (JPA)** | **NoSQL (MongoDB)** |
| --- | --- | --- |
| Estructura | Tablas fijas | Documentos flexibles |
| Relaciones | JOINs explícitos | Documentos anidados |
| Arrays | Tablas separadas | Arrays nativos |
| Esquema | Fijo | Flexible |
| Queries | SQL/JPQL | Queries de documentos |
| Escalabilidad | Vertical | Horizontal |

## **Cuándo Usar MongoDB**

* ✅ Datos con estructura variable
    
* ✅ Documentos complejos con anidación
    
* ✅ Escalabilidad horizontal importante
    
* ✅ Lecturas frecuentes de documentos completos
    
* ✅ Datos que no requieren transacciones complejas
    

## **Dev Services en Detalle**

Dev Services:

* Detecta si MongoDB está corriendo localmente
    
* Si no está, inicia un contenedor Docker automáticamente
    
* Configura la conexión automáticamente
    
* Limpia el contenedor al detener la aplicación
    

**Solo funciona en modo desarrollo**. Para producción, configura MongoDB manualmente.

## **Ejemplo Completo**

Nuestro demo muestra:

* Panache MongoDB con Active Record y Repository patterns
    
* Documentos anidados (location, secretBase)
    
* Arrays de valores (abilities, allies)
    
* Arrays de documentos anidados (missions)
    
* Queries en estructuras complejas
    
* Dev Services para MongoDB automático
    
* Operaciones CRUD completas
    

## **Conclusión**

MongoDB con Panache MongoDB en Quarkus proporciona acceso simple a bases de datos NoSQL. Dev Services elimina completamente la configuración manual, mientras que Panache MongoDB simplifica el código. La flexibilidad de MongoDB es perfecta para datos con estructuras complejas y variables.

## **Recursos**

* [Demo completo](file:///Users/josediaz/Projects/JoeDayz/jakartaee-2026/quarkus-demos/nosql/)
    
* [Quarkus MongoDB Panache Guide](https://quarkus.io/guides/mongodb-panache)
    
* [Quarkus Dev Services](https://quarkus.io/guides/dev-services)
    
* [MongoDB Documentation](https://www.mongodb.com/docs/)
