sql >> Database >  >> NoSQL >> MongoDB

Een eenvoudige tagging-implementatie met MongoDB

Dit artikel maakt deel uit van een reeks:• Een eenvoudige implementatie van tags met Elasticsearch
• Een eenvoudige tagging-implementatie met JPA
• Een geavanceerde tagging-implementatie met JPA
• Een eenvoudige tagging-implementatie met MongoDB (huidig ​​artikel)

1. Overzicht

In deze zelfstudie bekijken we een eenvoudige tagging-implementatie met Java en MongoDB.

Voor degenen die niet bekend zijn met het concept:een tag is een trefwoord dat wordt gebruikt als een 'label' om documenten in verschillende categorieën te groeperen. Hierdoor kunnen de gebruikers snel door vergelijkbare inhoud navigeren en het is vooral handig bij het verwerken van een grote hoeveelheid gegevens.

Dat gezegd hebbende, is het niet verwonderlijk dat deze techniek heel vaak wordt gebruikt in blogs. In dit scenario heeft elk bericht een of meer tags op basis van de behandelde onderwerpen. Wanneer de gebruiker klaar is met lezen, kan hij een van de tags volgen om meer inhoud met betrekking tot dat onderwerp te bekijken.

Laten we eens kijken hoe we dit scenario kunnen implementeren.

2. Afhankelijkheid

Om de database te doorzoeken, moeten we de MongoDB-stuurprogramma-afhankelijkheid opnemen in onze pom.xml :

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

De huidige versie van deze afhankelijkheid is hier te vinden.

3. Gegevensmodel

Laten we allereerst beginnen met het plannen van hoe een postdocument eruit zou moeten zien.

Om het simpel te houden, heeft ons gegevensmodel alleen een titel, die we ook gebruiken als document-ID, een auteur en enkele tags.

We slaan de tags op in een array, aangezien een bericht er waarschijnlijk meer dan één zal hebben:

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

We zullen ook de overeenkomstige Java-modelklasse maken:

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

    // getters and setters
}

4. Tags bijwerken

Nu we de database hebben opgezet en een aantal voorbeeldberichten hebben ingevoegd, gaan we kijken hoe we deze kunnen bijwerken.

Onze repository-klasse zal twee methoden bevatten om het toevoegen en verwijderen van tags af te handelen door de titel te gebruiken om ze te vinden. We retourneren ook een boolean om aan te geven of de zoekopdracht een element heeft bijgewerkt of niet:

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;
}

We gebruikten de addEachToSet methode in plaats van duwen voor de toevoeging, zodat als de tags er al zijn, we ze niet opnieuw zullen toevoegen.

Merk ook op dat de addToSet operator zou ook niet werken omdat het de nieuwe tags zou toevoegen als een geneste array, wat niet is wat we willen.

Een andere manier waarop we onze updates kunnen uitvoeren, is via de Mongo-shell. Laten we bijvoorbeeld de post JUnit5 updaten met Java. In het bijzonder willen we de tags Java . toevoegen en JUnit5 en verwijder de tags Lente en REST :

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. Vragen

Last but not least, laten we eens kijken naar enkele van de meest voorkomende vragen waarin we mogelijk geïnteresseerd zijn tijdens het werken met tags. Voor dit doel zullen we in het bijzonder profiteren van drie array-operators:

  • $in – geeft de documenten terug waar een veld een waarde bevat van de opgegeven array
  • $nin – geeft de documenten terug waar een veld geen waarde bevat van de opgegeven array
  • $all – geeft de documenten terug waar een veld alle waarden bevat van de opgegeven array

We zullen drie methoden definiëren om de berichten te doorzoeken met betrekking tot een verzameling tags die als argumenten zijn doorgegeven . Ze zullen de berichten retourneren die overeenkomen met ten minste één tag, alle tags en geen van de tags. We zullen ook een toewijzingsmethode maken om de conversie tussen een document en ons model af te handelen met behulp van Java 8's Stream API:

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;
}

Nogmaals, laten we ook eens kijken naar de shell-equivalente zoekopdrachten . We halen drie verschillende postverzamelingen op, respectievelijk getagd met MongoDB of Streamen API, getagd met zowel Java 8 en JUNI 5 en niet getagd met Groovy noch 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" ] } 
});

  1. mongod HostnameCanonicalizationWorker-fout op OS X

  2. Aan de slag met databaseautomatisering

  3. Omgaan met schemawijzigingen in Mongoose

  4. Sidekiq verwerkt wachtrij niet