133 lines
3.8 KiB
JavaScript
133 lines
3.8 KiB
JavaScript
const prisma = require("./client")
|
|
const { Prisma } = require("@prisma/client")
|
|
|
|
async function findLike(commentId, userId, db) {
|
|
const p = db || prisma
|
|
return p.commentLike.findUnique({
|
|
where: { commentId_userId: { commentId, userId } },
|
|
})
|
|
}
|
|
|
|
async function findLikesByUserAndCommentIds(userId, commentIds, db) {
|
|
const p = db || prisma
|
|
return p.commentLike.findMany({
|
|
where: { userId, commentId: { in: commentIds } },
|
|
select: { commentId: true },
|
|
})
|
|
}
|
|
|
|
async function setCommentLike({ commentId, userId, like }) {
|
|
return prisma.$transaction(async (tx) => {
|
|
const comment = await tx.comment.findUnique({
|
|
where: { id: commentId },
|
|
select: { id: true, likeCount: true },
|
|
})
|
|
if (!comment) throw new Error("Yorum bulunamadı.")
|
|
|
|
const existing = await findLike(commentId, userId, tx)
|
|
|
|
if (like) {
|
|
if (existing) {
|
|
return { liked: true, delta: 0, likeCount: comment.likeCount }
|
|
}
|
|
await tx.commentLike.create({
|
|
data: { commentId, userId },
|
|
})
|
|
const updated = await tx.comment.update({
|
|
where: { id: commentId },
|
|
data: { likeCount: { increment: 1 } },
|
|
select: { likeCount: true },
|
|
})
|
|
return { liked: true, delta: 1, likeCount: updated.likeCount }
|
|
}
|
|
|
|
if (!existing) {
|
|
return { liked: false, delta: 0, likeCount: comment.likeCount }
|
|
}
|
|
await tx.commentLike.delete({
|
|
where: { commentId_userId: { commentId, userId } },
|
|
})
|
|
const updated = await tx.comment.update({
|
|
where: { id: commentId },
|
|
data: { likeCount: { decrement: 1 } },
|
|
select: { likeCount: true },
|
|
})
|
|
return { liked: false, delta: -1, likeCount: updated.likeCount }
|
|
})
|
|
}
|
|
|
|
async function applyCommentLikeBatch(items = []) {
|
|
if (!items.length) return { inserted: 0, deleted: 0 }
|
|
|
|
const likes = items.filter((i) => i.like)
|
|
const unlikes = items.filter((i) => !i.like)
|
|
|
|
return prisma.$transaction(async (tx) => {
|
|
let inserted = 0
|
|
let deleted = 0
|
|
|
|
if (likes.length) {
|
|
const values = Prisma.join(
|
|
likes.map((i) => Prisma.sql`(${i.commentId}, ${i.userId})`)
|
|
)
|
|
const insertSql = Prisma.sql`
|
|
WITH input("commentId","userId") AS (VALUES ${values}),
|
|
ins AS (
|
|
INSERT INTO "CommentLike" ("commentId","userId")
|
|
SELECT "commentId","userId" FROM input
|
|
ON CONFLICT ("commentId","userId") DO NOTHING
|
|
RETURNING "commentId"
|
|
),
|
|
agg AS (
|
|
SELECT "commentId", COUNT(*)::int AS cnt FROM ins GROUP BY "commentId"
|
|
)
|
|
UPDATE "Comment" c
|
|
SET "likeCount" = c."likeCount" + agg.cnt
|
|
FROM agg
|
|
WHERE c.id = agg."commentId"
|
|
RETURNING agg.cnt
|
|
`
|
|
|
|
const rows = await tx.$queryRaw(insertSql)
|
|
if (Array.isArray(rows)) {
|
|
inserted = rows.reduce((sum, row) => sum + Number(row.cnt || 0), 0)
|
|
}
|
|
}
|
|
|
|
if (unlikes.length) {
|
|
const values = Prisma.join(
|
|
unlikes.map((i) => Prisma.sql`(${i.commentId}, ${i.userId})`)
|
|
)
|
|
const deleteSql = Prisma.sql`
|
|
WITH input("commentId","userId") AS (VALUES ${values}),
|
|
del AS (
|
|
DELETE FROM "CommentLike" cl
|
|
WHERE (cl."commentId", cl."userId") IN (SELECT "commentId","userId" FROM input)
|
|
RETURNING "commentId"
|
|
),
|
|
agg AS (
|
|
SELECT "commentId", COUNT(*)::int AS cnt FROM del GROUP BY "commentId"
|
|
)
|
|
UPDATE "Comment" c
|
|
SET "likeCount" = c."likeCount" - agg.cnt
|
|
FROM agg
|
|
WHERE c.id = agg."commentId"
|
|
RETURNING agg.cnt
|
|
`
|
|
|
|
const rows = await tx.$queryRaw(deleteSql)
|
|
if (Array.isArray(rows)) {
|
|
deleted = rows.reduce((sum, row) => sum + Number(row.cnt || 0), 0)
|
|
}
|
|
}
|
|
|
|
return { inserted, deleted }
|
|
})
|
|
}
|
|
|
|
module.exports = {
|
|
findLikesByUserAndCommentIds,
|
|
setCommentLike,
|
|
applyCommentLikeBatch,
|
|
}
|