sql >> Database teknologi >  >> NoSQL >> MongoDB

En simpel tagging-implementering med MongoDB

Denne artikel er en del af en serie:• En simpel tagging-implementering med Elasticsearch
• En simpel tagging-implementering med JPA
• En avanceret tagging-implementering med JPA
• En simpel tagging-implementering med MongoDB (aktuel artikel)

1. Oversigt

I denne øvelse tager vi et kig på en simpel tagging-implementering ved hjælp af Java og MongoDB.

For dem, der ikke kender konceptet, et tag er et nøgleord, der bruges som en "etiket" til at gruppere dokumenter i forskellige kategorier. Dette giver brugerne mulighed for hurtigt at navigere gennem lignende indhold, og det er især nyttigt, når de har at gøre med en stor mængde data.

Når det er sagt, er det ikke overraskende, at denne teknik er meget almindeligt brugt i blogs. I dette scenarie har hvert indlæg et eller flere tags i henhold til de dækkede emner. Når brugeren er færdig med at læse, kan han følge et af tags for at se mere indhold relateret til det emne.

Lad os se, hvordan vi kan implementere dette scenario.

2. Afhængighed

For at forespørge databasen skal vi inkludere MongoDB-driverafhængigheden i vores pom.xml :

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

Den aktuelle version af denne afhængighed kan findes her.

3. Datamodel

Først og fremmest, lad os starte med at planlægge, hvordan et postdokument skal se ud.

For at holde det enkelt vil vores datamodel kun have en titel, som vi også bruger som dokument-id, en forfatter og nogle tags.

Vi gemmer taggene i et array, da et indlæg sandsynligvis vil have mere end blot én:

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

Vi opretter også den tilsvarende Java-modelklasse:

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

    // getters and setters
}

4. Opdatering af tags

Nu hvor vi har konfigureret databasen og indsat et par eksempelindlæg, lad os se, hvordan vi kan opdatere dem.

Vores lagerklasse vil omfatte to metoder til at håndtere tilføjelse og fjernelse af tags ved at bruge titlen til at finde dem. Vi returnerer også en boolean for at angive, om forespørgslen opdaterede et element eller ej:

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

Vi brugte addEachToSet metode i stedet for push for tilføjelsen, så hvis taggene allerede er der, tilføjer vi dem ikke igen.

Bemærk også, at addToSet operatoren ville heller ikke fungere, da den ville tilføje de nye tags som et indlejret array, hvilket ikke er det, vi ønsker.

En anden måde, vi kan udføre vores opdateringer på, er gennem Mongo-skallen. Lad os for eksempel opdatere indlægget JUnit5 med Java. Især ønsker vi at tilføje tags Java og JEnhed5 og fjern taggene Forår og HVILE :

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. Forespørgsler

Sidst men ikke mindst, lad os gennemgå nogle af de mest almindelige forespørgsler, vi kan være interesserede i, mens vi arbejder med tags. Til dette formål vil vi især drage fordel af tre array-operatorer:

  • $in – returnerer de dokumenter, hvor et felt indeholder en værdi af det angivne array
  • $nin – returnerer de dokumenter, hvor et felt ikke indeholder nogen værdi af det angivne array
  • $all – returnerer de dokumenter, hvor et felt indeholder alle værdierne af det angivne array

Vi definerer tre metoder til at forespørge indlæggene i forhold til en samling af tags, der sendes som argumenter . De vil returnere de indlæg, der matcher mindst ét ​​tag, alle tags og ingen af ​​tags. Vi vil også oprette en kortlægningsmetode til at håndtere konverteringen mellem et dokument og vores model ved hjælp af 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;
}

Igen, lad os også tage et kig på de shell-ækvivalente forespørgsler . Vi henter tre forskellige indlægssamlinger, der er tagget med MongoDB eller Stream API, tagget med både Java 8 og JUnit 5 og ikke tagget med Groovy heller ikke 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. Henvisning til andre dokumenter efter streng i stedet for ObjectId

  2. Skift type felt inde i mongoDB aggregering, og bruger $lookup indeks på felter eller ej?

  3. Introduktion til distribueret cache i Hadoop

  4. Redis Connection via socket på Node.js