Einen großartigen Nest.js-Blog erstellen: Tags für Beiträge
Min-jun Kim
Dev Intern · Leapcell

Im vorherigen Tutorial haben wir die Besucherzählung zu unserem Blog hinzugefügt, damit wir visuell sehen können, wie beliebt jeder Artikel ist.
Der Blog sieht bereits recht vollständig aus, aber es scheint, als ob noch etwas fehlt. Ihr Blog hat bereits viele Artikel, und die Benutzer könnten sich darin verlieren... Wie können Benutzer also schnell die Themen finden, an denen sie interessiert sind?
Das stimmt, der Blog benötigt nun eine Tag-Funktion.
Tags werden verwendet, um das Thema und den Inhalt eines Artikels anzuzeigen. Sie können einem Artikel mehrere Schlüsselwörter zuweisen (z. B. "Technischer Leitfaden", "Nest.js", "Datenbank").
In den nächsten beiden Tutorials fügen wir unserem Blogsystem eine Tag-Funktion hinzu. In diesem Tutorial werden wir zunächst die Unterstützung für das Festlegen von Tags beim Erstellen und Bearbeiten von Artikeln implementieren.
Schritt 1: Datenmodellierung und Beziehungsaufbau
Erstellen der Tag-Entität
Zuerst erstellen wir ein entsprechendes Modul und eine Entität für dieses neue Konzept.
nest generate module tags nest generate service tags
Erstellen Sie tag.entity.ts
im Verzeichnis src/tags
:
// src/tags/tag.entity.ts import { Entity, Column, PrimaryColumn, ManyToMany } from 'typeorm'; import { Post } from '../posts/post.entity'; @Entity() export class Tag { @PrimaryColumn({ type: 'uuid', default: () => 'gen_random_uuid()' }) id: string; @Column({ unique: true }) name: string; @ManyToMany(() => Post, (post) => post.tags) posts: Post[]; }
Aktualisieren der Post-Entität zur Herstellung der Beziehung
Als Nächstes müssen wir die Datei src/posts/post.entity.ts
aktualisieren, um die Verknüpfung zwischen Beiträgen und Tags herzustellen.
Ein Beitrag kann mehrere Tags haben und ein Tag kann mit mehreren Beiträgen verknüpft sein. Dies ist eine Many-to-Many-Beziehung.
// src/posts/post.entity.ts import { Entity, Column, PrimaryColumn, CreateDateColumn, ManyToOne, ManyToMany, JoinTable } from 'typeorm'; import { Tag } from '../tags/tag.entity'; // ... andere Importe @Entity() export class Post { // ... andere Felder (id, title, content, etc.) @ManyToMany(() => Tag, (tag) => tag.posts, { cascade: true, // Ermöglicht das Erstellen neuer Tags über einen Beitrag }) @JoinTable() // @JoinTable muss auf einer Seite der Beziehung angegeben werden tags: Tag[]; // ... andere Beziehungen (Kommentare, Aufrufe, etc.) }
@JoinTable()
ist ein Decorator, der zur Definition einer Many-to-Many-Beziehung erforderlich ist. Sie müssen eine Join-Tabellepost_tags_tag
erstellen, um die Verknüpfung zwischenPost
undTag
zu verwalten.
Aktualisieren der Datenbanktabellenstruktur
Führen Sie die folgenden SQL-Anweisungen aus, um die neuen Tabellen und Felder zu erstellen.
-- Erstellt die Tag-Tabelle CREATE TABLE "tag" ( "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), "name" VARCHAR UNIQUE NOT NULL ); -- Erstellt die post_tags_tag Join-Tabelle CREATE TABLE "post_tags_tag" ( "postId" UUID REFERENCES "post" ON DELETE CASCADE, "tagId" UUID REFERENCES "tag" ON DELETE CASCADE, PRIMARY KEY ("postId", "tagId") );
Wenn Ihre Datenbank auf Leapcell erstellt wurde,
können Sie SQL-Anweisungen ganz einfach über die grafische Benutzeroberfläche ausführen. Gehen Sie dazu auf der Website zur Seite Datenbankverwaltung, fügen Sie die obigen Anweisungen in die SQL-Schnittstelle ein und führen Sie sie aus.
Schritt 2: Implementierung der Backend-Logik
Wir müssen einen Service schreiben, um das Erstellen und Finden von Tags zu handhaben, und den PostsService
aktualisieren, um diese Beziehungen beim Erstellen eines Beitrags zu verwalten.
Schreiben des TagsService
Die Logik für diesen Service ist relativ einfach und konzentriert sich hauptsächlich auf das Finden oder Erstellen von Tags.
Öffnen Sie src/tags/tags.module.ts
und registrieren Sie TypeOrmModule
.
// src/tags/tags.module.ts import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Tag } from './tag.entity'; import { TagsService } from './tags.service'; @Module({ imports: [TypeOrmModule.forFeature([Tag])], providers: [TagsService], exports: [TagsService], // Exportieren Sie den Service für andere Module zur Verwendung }) export class TagsModule {}
In src/tags/tags.service.ts
:
// src/tags/tags.service.ts import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository, In } from 'typeorm'; import { Tag } from './tag.entity'; @Injectable() export class TagsService { constructor( @InjectRepository(Tag) private tagsRepository: Repository<Tag> ) {} // Tags finden oder erstellen async findOrCreate(tagNames: string[]): Promise<Tag[]> { const existingTags = await this.tagsRepository.findBy({ name: In(tagNames) }); const existingTagNames = existingTags.map((tag) => tag.name); const newTagNames = tagNames.filter((name) => !existingTagNames.includes(name)); const newTags = newTagNames.map((name) => this.tagsRepository.create({ name })); await this.tagsRepository.save(newTags); return [...existingTags, ...newTags]; } }
Aktualisieren des PostsService zur Behandlung der Verknüpfung
Wir müssen die Methoden create
und findOne
ändern.
Importieren Sie zuerst das TagsModule
in das PostsModule
.
// src/posts/posts.module.ts import { TagsModule } from '../tags/tags.module'; @Module({ imports: [TypeOrmModule.forFeature([Post]), CommentsModule, TrackingModule, TagsModule], // ... }) export class PostsModule {}
Dann aktualisieren Sie src/posts/posts.service.ts
:
// src/posts/posts.service.ts import { Injectable } from '@nestjs/common'; import { TagsService } from '../tags/tags.service'; // ... andere Importe @Injectable() export class PostsService { constructor( @InjectRepository(Post) private postsRepository: Repository<Post>, private readonly tagsService: TagsService // TagsService injizieren ) {} // Die Methode create aktualisieren async create(post: Omit<Partial<Post>, 'tags'> & { tags: string }): Promise<Post> { const tagNames = post.tags .split(',') .map((tag) => tag.trim()) .filter(Boolean); const tags = await this.tagsService.findOrCreate(tagNames); const newPost = this.postsRepository.create({ ...post, tags, }); return this.postsRepository.save(newPost); } // Die Methode findOne aktualisieren, um verwandte Daten zu laden findOne(id: string): Promise<Post | null> { return this.postsRepository.findOne({ where: { id }, relations: ['tags'], // Tags laden }); } // ... andere Methoden }
Schritt 3: Integration der Frontend-Seite
Der letzte Schritt besteht darin, die EJS-Vorlagen zu ändern, um das Festlegen von Tags beim Erstellen und Bearbeiten von Beiträgen zu unterstützen und die Tags auf der Detailseite des Beitrags anzuzeigen.
Aktualisieren der Seite Neu/Bearbeiten Beitrag
Öffnen Sie views/new-post.ejs
und fügen Sie ein Formularfeld für die Eingabe von Tags hinzu.
<form action="/posts" method="POST" class="post-form"> <div class="form-group"> <label for="tags">Tags (kommagetrennt)</label> <input type="text" id="tags" name="tags" /> </div> <button type="submit">Absenden</button> </form>
Zu vereinfachung verwenden wir hier eine kommagetrennte Eingabe für mehrere Tags. In einem realen Projekt könnten Sie komplexere UI-Komponenten und Logik verwenden, wie z. B. eine spezielle Tag-Eingabekomponente, eine automatische Übereinstimmung vorhandener Tags usw., um die Benutzererfahrung zu verbessern.
Aktualisieren der Detailseite des Beitrags
Öffnen Sie views/post.ejs
und zeigen Sie die Tags in den Metadaten des Beitrags an.
<article class="post-detail"> <h1><%= post.title %></h1> <small> <%= new Date(post.createdAt).toLocaleDateString() %> | Aufrufe: <%= viewCount %> </small> <div class="post-content"><%- post.content %></div> <% if (post.tags && post.tags.length > 0) { %> <div class="tags-section"> <strong>Tags:</strong> <% post.tags.forEach(tag => { %> <a href="/tags/<%= tag.id %>" class="tag-item"><%= tag.name %></a> <% }) %> </div> <% } %> </article>
Ausführen und Testen
Starten Sie Ihre Anwendung neu:
npm run start:dev
Öffnen Sie Ihren Browser und gehen Sie zu: http://localhost:3000/
Erstellen Sie einen neuen Beitrag, und Sie sehen unten das Eingabefeld für Tags.
Geben Sie einige Tags ein, getrennt durch Kommas, z. B. Nest.js, Tutorial
, und senden Sie sie ab.
Nach dem Absenden gehen Sie zur Detailseite des Beitrags, und Sie werden sehen, dass die Tags des Beitrags nun erfolgreich angezeigt werden.
Ihr Blog unterstützt nun die Erstellung und Anzeige von Tags. Benutzer können jedoch Artikel noch nicht nach Tags filtern. Diesen Feature werden wir im nächsten Tutorial implementieren.
Frühere Tutorials:
- Einen großartigen Nest.js-Blog erstellen: Besucheranalysen
- Einen großartigen Nest.js-Blog erstellen: Volltextsuche für Beiträge
- Einen großartigen Nest.js-Blog erstellen: Bilder hochladen
- Einen großartigen Nest.js-Blog erstellen: Kommentare beantworten
- Einen großartigen Nest.js-Blog erstellen: Kommentarsystem
- Einen großartigen Nest.js-Blog erstellen: Autorisierung hinzufügen
- Einen großartigen Nest.js-Blog erstellen: Benutzerverwaltung hinzufügen
- 10 Minuten vom ersten Code bis zum Live-Deployment: Ein super-schneller Nest.js Blog-Kurs