Relasi Many-to-Many di Prisma

Prisma adalah sebuah pustaka JavaScript yang sangat powerful. Beberapa database seperti PostgreSQL, mysql, dan sqlite, sudah kucoba tanpa masalah dengan menggunakan pustaka ini. Dari generate tabel-tabel sampai melakukan query data.

Dari sekian banyak pustaka yang kugunakan, Prisma ini bisa dibilang masih awam. Sulitnya mencari tutorial menjadi alasan utama.

Berikut di sini, aku akan mencoba menjelaskan bagaimana menggunakan relasi many-to-many di Prisma. Sebagai contoh, aku membuat 2 buah tabel Post dan Tag untuk menyimpan artikel yang memiliki beberapa tanda.

Tabel Post:

model Post {
    id        Int      @id @default(autoincrement())
    title     String
    content   String?
    tags      Tag[]
    createdAt DateTime @default(now())
}

dan tabel Tag:

model Tag {
    id    Int    @id @default(autoincrement())
    name  String @unique
    slug  String @unique
    posts Post[]
}

Untuk mencari id dari Tag:

export const getTagIds = async (tagcsv: string) => {
    const ids = [];

    if (tagcsv) {
        const tagNames = tagcsv.split(',');

        const tags = tagNames.map(async (tagName) => {
            const name = tagName.trim().toLowerCase();
            const slug = slugify(name); // dari slugify

            let tag = await db.tag.findFirst({
                where: { slug: slug }
            });

            if (!tag) {
                tag = await db.tag.create({
                    data: { name, slug }
                });
            }

            return tag;
        });

        for (const tag of tags) {
            ids.push({
                id: (await tag)?.id
            });
        }
    }

    return ids;
}

Untuk isi dari variabel tagcvs bisa seperti ini:

const tagcsv = 'merah, kuning, hijau';  // dari form input di web

Untuk melakukan penyimpanan baru pada sebuah artikel yang disimpan di tabel Post:

const ids = await getTagIds(tagcsv);
        
const post = await db.post.create({
    data: {
        title: 'Lorem Ipsum',
        content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
        tags: {
            connect: [...ids]
        }
    }
});

Untuk proses update berbeda dengan penyimpanan baru:

const ids = await getTagIds(tagcsv);

const post = await db.post.update({
    where: { id: 1 },
    data: {
        title: 'Lorem Ipsum 2',
        content: 'Nunc turpis magna, cursus at placerat tempus, aliquam eget lorem.',
        tags: {
            set: [...ids]
        }
    }
});

Untuk proses seeding sendiri pun berbeda:

const tags = ['merah', 'kuning', 'hijau'];

for (let i = 0; i < 20; i++) {
    const words = faker.random.words(5).split(' '); // dari @faker-js/faker
    const title = words.map((word) => {
        return word[0].toUpperCase() + word.substring(1);
    }).join(" ");

    const content = faker.lorem.paragraphs(3, '\n\n');

    await prisma.post.create({
        data: {
            title,
            content,
            tags: {
                connectOrCreate: tags.map((name) => {
                    return {
                        where: { slug: name },
                        create: {
                            name,
                            slug: name
                        }
                    }
                })
            }
        }
    });
}

Cara ini aku gunakan untuk melakukan proses create dan update untuk relasi many-to-many di Prisma. Entah kenapa berbeda-beda caranya supaya berjalan dengan baik, mungkin ada bagian dari dokumentasi yang terlewatkan.

Connect with me:

Comments

Spammy comment will be deleted. Markdown syntax is supported.