Optimize again comments list sql query
This commit is contained in:
parent
3f3530c3db
commit
0b96a0fb77
|
@ -49,7 +49,7 @@ function getCommentSort (value: string, lastSort: OrderItem = [ 'id', 'ASC' ]):
|
||||||
|
|
||||||
if (field === 'totalReplies') {
|
if (field === 'totalReplies') {
|
||||||
return [
|
return [
|
||||||
[ Sequelize.literal('"totalReplies"'), direction ],
|
[ 'totalReplies', direction ],
|
||||||
lastSort
|
lastSort
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ export class VideoCommentListQueryBuilder extends AbstractRunQuery {
|
||||||
|
|
||||||
private innerSelect = ''
|
private innerSelect = ''
|
||||||
private innerJoins = ''
|
private innerJoins = ''
|
||||||
|
private innerLateralJoins = ''
|
||||||
private innerWhere = ''
|
private innerWhere = ''
|
||||||
|
|
||||||
private readonly built = {
|
private readonly built = {
|
||||||
|
@ -59,6 +60,10 @@ export class VideoCommentListQueryBuilder extends AbstractRunQuery {
|
||||||
private readonly options: ListVideoCommentsOptions
|
private readonly options: ListVideoCommentsOptions
|
||||||
) {
|
) {
|
||||||
super(sequelize)
|
super(sequelize)
|
||||||
|
|
||||||
|
if (this.options.includeReplyCounters && !this.options.videoId) {
|
||||||
|
throw new Error('Cannot include reply counters without videoId')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async listComments <T extends Model> () {
|
async listComments <T extends Model> () {
|
||||||
|
@ -97,6 +102,7 @@ export class VideoCommentListQueryBuilder extends AbstractRunQuery {
|
||||||
this.innerQuery = `${this.innerSelect} ` +
|
this.innerQuery = `${this.innerSelect} ` +
|
||||||
`FROM "videoComment" AS "VideoCommentModel" ` +
|
`FROM "videoComment" AS "VideoCommentModel" ` +
|
||||||
`${this.innerJoins} ` +
|
`${this.innerJoins} ` +
|
||||||
|
`${this.innerLateralJoins} ` +
|
||||||
`${this.innerWhere} ` +
|
`${this.innerWhere} ` +
|
||||||
`${this.getOrder()} ` +
|
`${this.getOrder()} ` +
|
||||||
`${this.getInnerLimit()}`
|
`${this.getInnerLimit()}`
|
||||||
|
@ -284,11 +290,6 @@ export class VideoCommentListQueryBuilder extends AbstractRunQuery {
|
||||||
toSelect.push(this.tableAttributes.getAvatarAttributes())
|
toSelect.push(this.tableAttributes.getAvatarAttributes())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.includeReplyCounters === true) {
|
|
||||||
toSelect.push(this.getTotalRepliesSelect())
|
|
||||||
toSelect.push(this.getAuthorTotalRepliesSelect())
|
|
||||||
}
|
|
||||||
|
|
||||||
this.select = this.buildSelect(toSelect)
|
this.select = this.buildSelect(toSelect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,6 +308,14 @@ export class VideoCommentListQueryBuilder extends AbstractRunQuery {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.options.includeReplyCounters === true) {
|
||||||
|
this.buildTotalRepliesSelect()
|
||||||
|
this.buildAuthorTotalRepliesSelect()
|
||||||
|
|
||||||
|
toSelect.push('"totalRepliesFromVideoAuthor"."count" AS "totalRepliesFromVideoAuthor"')
|
||||||
|
toSelect.push('"totalReplies"."count" AS "totalReplies"')
|
||||||
|
}
|
||||||
|
|
||||||
this.innerSelect = this.buildSelect(toSelect)
|
this.innerSelect = this.buildSelect(toSelect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,26 +353,32 @@ export class VideoCommentListQueryBuilder extends AbstractRunQuery {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
private getTotalRepliesSelect () {
|
private buildTotalRepliesSelect () {
|
||||||
const blockWhereString = this.getBlockWhere('replies', 'videoChannel').join(' AND ')
|
const blockWhereString = this.getBlockWhere('replies', 'videoChannel').join(' AND ')
|
||||||
|
|
||||||
return `(` +
|
// Help the planner by providing videoId that should filter out many comments
|
||||||
`SELECT COUNT("replies"."id") FROM "videoComment" AS "replies" ` +
|
this.replacements.videoId = this.options.videoId
|
||||||
`LEFT JOIN "video" ON "video"."id" = "replies"."videoId" ` +
|
|
||||||
|
this.innerLateralJoins += `LEFT JOIN LATERAL (` +
|
||||||
|
`SELECT COUNT("replies"."id") AS "count" FROM "videoComment" AS "replies" ` +
|
||||||
|
`INNER JOIN "video" ON "video"."id" = "replies"."videoId" AND "replies"."videoId" = :videoId ` +
|
||||||
`LEFT JOIN "videoChannel" ON "video"."channelId" = "videoChannel"."id" ` +
|
`LEFT JOIN "videoChannel" ON "video"."channelId" = "videoChannel"."id" ` +
|
||||||
`WHERE "replies"."originCommentId" = "VideoCommentModel"."id" ` +
|
`WHERE "replies"."originCommentId" = "VideoCommentModel"."id" ` +
|
||||||
`AND "deletedAt" IS NULL ` +
|
`AND "deletedAt" IS NULL ` +
|
||||||
`AND ${blockWhereString} ` +
|
`AND ${blockWhereString} ` +
|
||||||
`) AS "totalReplies"`
|
`) "totalReplies" ON TRUE `
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAuthorTotalRepliesSelect () {
|
private buildAuthorTotalRepliesSelect () {
|
||||||
return `(` +
|
// Help the planner by providing videoId that should filter out many comments
|
||||||
`SELECT COUNT("replies"."id") FROM "videoComment" AS "replies" ` +
|
this.replacements.videoId = this.options.videoId
|
||||||
`INNER JOIN "video" ON "video"."id" = "replies"."videoId" ` +
|
|
||||||
|
this.innerLateralJoins += `LEFT JOIN LATERAL (` +
|
||||||
|
`SELECT COUNT("replies"."id") AS "count" FROM "videoComment" AS "replies" ` +
|
||||||
|
`INNER JOIN "video" ON "video"."id" = "replies"."videoId" AND "replies"."videoId" = :videoId ` +
|
||||||
`INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ` +
|
`INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ` +
|
||||||
`WHERE "replies"."originCommentId" = "VideoCommentModel"."id" AND "replies"."accountId" = "videoChannel"."accountId"` +
|
`WHERE "replies"."originCommentId" = "VideoCommentModel"."id" AND "replies"."accountId" = "videoChannel"."accountId"` +
|
||||||
`) AS "totalRepliesFromVideoAuthor"`
|
`) "totalRepliesFromVideoAuthor" ON TRUE `
|
||||||
}
|
}
|
||||||
|
|
||||||
private getOrder () {
|
private getOrder () {
|
||||||
|
|
|
@ -169,6 +169,13 @@ describe('Test video comments', function () {
|
||||||
expect(body.data[2].totalReplies).to.equal(0)
|
expect(body.data[2].totalReplies).to.equal(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should list the and sort them by total replies', async function () {
|
||||||
|
const body = await command.listThreads({ videoId: videoUUID, sort: 'totalReplies' })
|
||||||
|
|
||||||
|
expect(body.data[2].text).to.equal('my super first comment')
|
||||||
|
expect(body.data[2].totalReplies).to.equal(3)
|
||||||
|
})
|
||||||
|
|
||||||
it('Should delete a reply', async function () {
|
it('Should delete a reply', async function () {
|
||||||
await command.delete({ videoId, commentId: replyToDeleteId })
|
await command.delete({ videoId, commentId: replyToDeleteId })
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue