Skip to main content

Command Palette

Search for a command to run...

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

Updated
5 min read

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

JoeDayz

52 posts

Community Guy | Java Champion | AWS Architect | Software Architect