Uma implementação de marcação simples com o MongoDB

Uma implementação de marcação simples com o MongoDB

1. Visão geral

Neste tutorial, daremos uma olhada em uma implementação de marcação simples usando Java e MongoDB.

Para quem não está familiarizado com o conceito,a tag is a keyword used as a “label” to group documents into different categories. Isso permite que os usuários naveguem rapidamente por conteúdo semelhante e é especialmente útil ao lidar com uma grande quantidade de dados.

Dito isso, não é surpreendente que essa técnica seja muito comumente usada em blogs. Nesse cenário, cada postagem possui uma ou mais tags de acordo com os tópicos abordados. Quando o usuário termina de ler, ele pode seguir uma das tags para visualizar mais conteúdo relacionado a esse tópico.

Vamos ver como podemos implementar este cenário.

2. Dependência

Para consultar o banco de dados, teremos que incluir a dependência do driver MongoDB em nossopom.xml:


    org.mongodb
    mongo-java-driver
    3.6.3

A versão atual desta dependência pode ser encontradahere.

3. Modelo de dados

Em primeiro lugar, vamos começar planejando a aparência de um documento de postagem.

Para simplificar, nosso modelo de dados terá apenas um título, que também usaremos como o id do documento, um autor e algumas tags.

Iremos armazenar as tags dentro de uma matriz, pois uma postagem provavelmente terá mais de uma:

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

Também criaremos a classe de modelo Java correspondente:

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

    // getters and setters
}

4. Atualizando tags

Agora que configuramos o banco de dados e inserimos alguns posts de amostra, vamos ver como podemos atualizá-los.

Our repository class will include two methods to handle the addition and removal of tags usando o título para encontrá-los. Também retornaremos um booleano para indicar se a consulta atualizou um elemento ou não:

public boolean addTags(String title, List 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 tags) {
    UpdateResult result = collection.updateOne(
      new BasicDBObject(DBCollection.ID_FIELD_NAME, title),
      Updates.pullAll(TAGS_FIELD, tags));
    return result.getModifiedCount() == 1;
}

Usamos o métodoaddEachToSet em vez depush para a adição, de modo que, se as tags já estiverem lá, não as adicionemos novamente.

Observe também que o operadoraddToSet também não funcionaria, pois adicionaria as novas tags como uma matriz aninhada que não é o que queremos.

Another way we can perform our updates is through the Mongo shell. Por exemplo, vamos atualizar o postJUnit5 with Java. Em particular, queremos adicionar as tagsJavae JUnit5 e remover as tagsSpringeREST:

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, mas não menos importante, vamos examinar algumas das consultas mais comuns nas quais podemos estar interessados ​​ao trabalhar com tags. Para este propósito, tiraremos vantagem de três operadores de array em particular:

  • $in – retorna os documentos ondea field contains any value da matriz especificada

  • $nin – retorna os documentos ondea field doesn’t contain any value da matriz especificada

  • $all – retorna os documentos ondea field contains all the values da matriz especificada

We’ll define three methods to query the posts in relation to a collection of tags passed as arguments. Eles retornarão as postagens que correspondem a pelo menos uma tag, todas as tags e nenhuma delas. Também criaremos um método de mapeamento para lidar com a conversão entre um documento e nosso modelo usando a API Stream do Java 8:

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

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

public List postsWithoutTags(String... tags) {
    FindIterable 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) document.get(TAGS_FIELD));
    return post;
}

Novamente,let’s also take a look at the shell equivalent queries. Iremos buscar três pós-coleções diferentes, respectivamente marcadas comMongoDB ouStream API, marcadas comJava 8eJUnit 5e não marcadas comGroovy nemScala:

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

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

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

6. Conclusão

Neste artigo, mostramos como criar um mecanismo de marcação. Obviamente, podemos usar e readaptar essa mesma metodologia para outros fins, além de um blog.

Se você estiver interessado em aprender mais sobre MongoDB,we encourage you to read this introductory article.

Como sempre, todo o código do exemplo está disponívelover on the Github project.