sql >> Base de Datos >  >> NoSQL >> MongoDB

Una implementación de etiquetado simple con MongoDB

Este artículo es parte de una serie:• Una implementación de etiquetado simple con Elasticsearch
• Una implementación de etiquetado simple con JPA
• Una implementación de etiquetado avanzado con JPA
• Una implementación de etiquetado simple con MongoDB (artículo actual)

1. Resumen

En este tutorial, veremos una implementación de etiquetado simple usando Java y MongoDB.

Para quienes no estén familiarizados con el concepto, una etiqueta es una palabra clave que se utiliza como "etiqueta" para agrupar documentos en diferentes categorías. Esto permite a los usuarios navegar rápidamente por contenido similar y es especialmente útil cuando se trata de una gran cantidad de datos.

Dicho esto, no es de extrañar que esta técnica se utilice con mucha frecuencia en los blogs. En este escenario, cada publicación tiene una o más etiquetas según los temas tratados. Cuando el usuario termina de leer, puede seguir una de las etiquetas para ver más contenido relacionado con ese tema.

Veamos cómo podemos implementar este escenario.

2. Dependencia

Para consultar la base de datos, tendremos que incluir la dependencia del controlador MongoDB en nuestro pom.xml :

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.6.3</version>
</dependency>

La versión actual de esta dependencia se puede encontrar aquí.

3. Modelo de datos

En primer lugar, comencemos por planificar cómo debería ser un documento de publicación.

Para simplificar, nuestro modelo de datos solo tendrá un título, que también usaremos como la identificación del documento, un autor y algunas etiquetas.

Guardaremos las etiquetas dentro de una matriz ya que una publicación probablemente tendrá más de una:

{
    "_id" : "Java 8 and MongoDB",
    "author" : "Donato Rimenti",
    "tags" : ["Java", "MongoDB", "Java 8", "Stream API"]
}

También crearemos la clase de modelo de Java correspondiente:

public class Post {
    private String title;
    private String author;
    private List<String> tags;

    // getters and setters
}

4. Actualización de etiquetas

Ahora que hemos configurado la base de datos e insertado un par de publicaciones de muestra, veamos cómo podemos actualizarlas.

Nuestra clase de repositorio incluirá dos métodos para manejar la adición y eliminación de etiquetas usando el título para encontrarlos. También devolveremos un valor booleano para indicar si la consulta actualizó un elemento o no:

public boolean addTags(String title, List<String> tags) {
    UpdateResult result = collection.updateOne(
      new BasicDBObject(DBCollection.ID_FIELD_NAME, title), 
      Updates.addEachToSet(TAGS_FIELD, tags));
    return result.getModifiedCount() == 1;
}

public boolean removeTags(String title, List<String> tags) {
    UpdateResult result = collection.updateOne(
      new BasicDBObject(DBCollection.ID_FIELD_NAME, title), 
      Updates.pullAll(TAGS_FIELD, tags));
    return result.getModifiedCount() == 1;
}

Usamos el addEachToSet método en lugar de empujar para la adición, de modo que si las etiquetas ya están allí, no las agregaremos de nuevo.

Observe también que el addToSet El operador tampoco funcionaría ya que agregaría las nuevas etiquetas como una matriz anidada que no es lo que queremos.

Otra forma en que podemos realizar nuestras actualizaciones es a través del shell de Mongo. Por ejemplo, actualicemos la publicación JUnit5 con Java. En particular, queremos agregar las etiquetas Java y JUnidad5 y elimina las etiquetas Primavera y DESCANSO :

db.posts.updateOne(
    { _id : "JUnit 5 with Java" }, 
    { $addToSet : 
        { "tags" : 
            { $each : ["Java", "JUnit5"] }
        }
});

db.posts.updateOne(
    {_id : "JUnit 5 with Java" },
    { $pull : 
        { "tags" : { $in : ["Spring", "REST"] }
    }
});

5. Consultas

Por último, pero no menos importante, repasemos algunas de las consultas más comunes que pueden interesarnos al trabajar con etiquetas. Para este propósito, aprovecharemos tres operadores de matrices en particular:

  • $ en – devuelve los documentos donde un campo contiene algún valor de la matriz especificada
  • $nin – devuelve los documentos donde un campo no contiene ningún valor de la matriz especificada
  • $todos – devuelve los documentos donde un campo contiene todos los valores de la matriz especificada

Definiremos tres métodos para consultar las publicaciones en relación con una colección de etiquetas pasadas como argumentos . Devolverán las publicaciones que coincidan con al menos una etiqueta, todas las etiquetas y ninguna de las etiquetas. También crearemos un método de mapeo para manejar la conversión entre un documento y nuestro modelo utilizando la API Stream de Java 8:

public List<Post> postsWithAtLeastOneTag(String... tags) {
    FindIterable<Document> results = collection
      .find(Filters.in(TAGS_FIELD, tags));
    return StreamSupport.stream(results.spliterator(), false)
      .map(TagRepository::documentToPost)
      .collect(Collectors.toList());
}

public List<Post> postsWithAllTags(String... tags) {
    FindIterable<Document> results = collection
      .find(Filters.all(TAGS_FIELD, tags));
    return StreamSupport.stream(results.spliterator(), false)
      .map(TagRepository::documentToPost)
      .collect(Collectors.toList());
}

public List<Post> postsWithoutTags(String... tags) {
    FindIterable<Document> results = collection
      .find(Filters.nin(TAGS_FIELD, tags));
    return StreamSupport.stream(results.spliterator(), false)
      .map(TagRepository::documentToPost)
      .collect(Collectors.toList());
}

private static Post documentToPost(Document document) {
    Post post = new Post();
    post.setTitle(document.getString(DBCollection.ID_FIELD_NAME));
    post.setAuthor(document.getString("author"));
    post.setTags((List<String>) document.get(TAGS_FIELD));
    return post;
}

Nuevamente, echemos un vistazo a las consultas equivalentes de shell . Buscaremos tres colecciones de publicaciones diferentes etiquetadas respectivamente con MongoDB o Transmitir API, etiquetada con Java 8 y JUnidad 5 y no etiquetado con Groovy ni Scala :

db.posts.find({
    "tags" : { $in : ["MongoDB", "Stream API" ] } 
});

db.posts.find({
    "tags" : { $all : ["Java 8", "JUnit 5" ] } 
});

db.posts.find({
    "tags" : { $nin : ["Groovy", "Scala" ] } 
});