Skip to main content

Command Palette

Search for a command to run...

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

Published
•5 min read•View as Markdown

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

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

Cuando ejecutas mvn quarkus:dev, verás:

Dev Services for MongoDB started.

Panache MongoDB

Panache MongoDB proporciona dos patrones similares a Panache para SQL:

Active Record Pattern

@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

@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:

@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

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

3. Arrays de Documentos

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

// 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

// 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:

@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

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

Buscar

// 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

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

Eliminar

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

Ejemplo Completo: Estructura Compleja

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ísticaSQL (JPA)NoSQL (MongoDB)
EstructuraTablas fijasDocumentos flexibles
RelacionesJOINs explícitosDocumentos anidados
ArraysTablas separadasArrays nativos
EsquemaFijoFlexible
QueriesSQL/JPQLQueries de documentos
EscalabilidadVerticalHorizontal

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

More from this blog