MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

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



Este artigo faz parte de uma série:• Uma implementação de marcação simples com o Elasticsearch
• Uma implementação de marcação simples com JPA
• Uma implementação de marcação avançada com JPA
• Uma implementação de marcação simples com MongoDB (artigo atual)

1. Visão geral


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

Para aqueles que não estão familiarizados com o conceito, uma tag é uma palavra-chave usada como um “rótulo” para agrupar documentos em diferentes categorias. Isso permite que os usuários naveguem rapidamente por conteúdo semelhante e é especialmente útil ao lidar com uma grande quantidade de dados.

Dito isto, não é de surpreender que essa técnica seja muito usada em blogs. Nesse cenário, cada postagem possui uma ou mais tags de acordo com os tópicos abordados. Ao terminar a leitura, o usuário pode seguir uma das tags para visualizar mais conteúdos relacionados 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 nosso pom.xml :
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.6.3</version>
</dependency>

A versão atual dessa dependência pode ser encontrada aqui.

3. Modelo de dados


Primeiro de tudo, vamos começar planejando como um documento de postagem deve ser.

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

Armazenaremos as tags dentro de um array, já que um post provavelmente terá mais do que apenas um:
{
    "_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<String> tags;

    // getters and setters
}

4. Atualizando tags


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

Nossa classe de repositório incluirá dois métodos para lidar com a adição e remoção de 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<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 o addEachToSet método em vez de push para a adição para que, se as tags já estiverem lá, não as adicionaremos novamente.

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

Outra maneira de realizar nossas atualizações é por meio do shell Mongo. Por exemplo, vamos atualizar a postagem JUnit5 com Java. Em particular, queremos adicionar as tags Java e JUnidade5 e remova as tags Primavera e Descansar :
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 analisar algumas das consultas mais comuns nas quais podemos estar interessados ​​ao trabalhar com tags. Para isso, vamos aproveitar três operadores de array em particular:
  • $in – retorna os documentos em que um campo contém qualquer valor da matriz especificada
  • $nin – retorna os documentos em que um campo não contém nenhum valor da matriz especificada
  • $todos – retorna os documentos onde um campo contém todos os valores da matriz especificada

Vamos definir três métodos para consultar as postagens em relação a uma coleção de tags passadas como argumentos . Eles retornarão as postagens que correspondem a pelo menos uma tag, todas as tags e nenhuma das tags. 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<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;
}

Novamente, vamos também dar uma olhada nas consultas equivalentes ao shell . Buscaremos três coleções de postagens diferentes marcadas respectivamente com MongoDB ou Transmitir API, marcada com Java 8 e Junit 5 e não marcado com Groovy nem 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" ] } 
});