enable to fetch replies recursively
This commit is contained in:
parent
86342538aa
commit
15f06a1d50
2 changed files with 70 additions and 13 deletions
|
@ -0,0 +1,52 @@
|
|||
export class noteRepliesFunction1658656633972 {
|
||||
name = 'noteRepliesFunction1658656633972'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`
|
||||
CREATE OR REPLACE FUNCTION note_replies(start_id varchar, max_depth integer, max_breadth integer) RETURNS TABLE (id VARCHAR) AS
|
||||
$$
|
||||
SELECT DISTINCT id FROM (
|
||||
WITH RECURSIVE tree (id, ancestors, depth) AS (
|
||||
SELECT start_id, '{}'::VARCHAR[], 0
|
||||
UNION
|
||||
SELECT
|
||||
note.id,
|
||||
CASE
|
||||
WHEN note."replyId" = tree.id THEN tree.ancestors || note."replyId"
|
||||
ELSE tree.ancestors || note."renoteId"
|
||||
END,
|
||||
depth + 1
|
||||
FROM note, tree
|
||||
WHERE (
|
||||
note."replyId" = tree.id
|
||||
OR
|
||||
(
|
||||
-- get renotes but not pure renotes
|
||||
note."renoteId" = tree.id
|
||||
AND
|
||||
(
|
||||
note.text IS NOT NULL
|
||||
OR
|
||||
CARDINALITY(note."fileIds") != 0
|
||||
OR
|
||||
note."hasPoll" = TRUE
|
||||
)
|
||||
)
|
||||
) AND depth < max_depth
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
-- apply the limit per node
|
||||
row_number() OVER (PARTITION BY ancestors[array_upper(ancestors, 1)]) AS nth_child
|
||||
FROM tree
|
||||
WHERE depth > 0
|
||||
) AS recursive WHERE nth_child < max_breadth
|
||||
$$
|
||||
LANGUAGE SQL
|
||||
`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`DROP FUNCTION note_replies`);
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@ export const meta = {
|
|||
requireCredential: false,
|
||||
requireCredentialPrivateMode: true,
|
||||
|
||||
description: 'Get a list of children of a notes. Children includes replies as well as quote renotes that quote the respective post. A post will not be duplicated if it is a reply and a quote of a note in this thread. For depths larger than 1 the threading has to be computed by the client.',
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
optional: false, nullable: false,
|
||||
|
@ -27,7 +29,20 @@ export const paramDef = {
|
|||
type: 'object',
|
||||
properties: {
|
||||
noteId: { type: 'string', format: 'misskey:id' },
|
||||
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
|
||||
limit: {
|
||||
description: 'The maximum number of replies/quotes to show per parent note, i.e. the maximum number of children each note may have.',
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100,
|
||||
default: 10,
|
||||
},
|
||||
depth: {
|
||||
description: 'The number of layers of replies to fetch at once. Defaults to 1 for backward compatibility.',
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 100,
|
||||
default: 1,
|
||||
},
|
||||
sinceId: { type: 'string', format: 'misskey:id' },
|
||||
untilId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
|
@ -37,17 +52,7 @@ export const paramDef = {
|
|||
// eslint-disable-next-line import/no-default-export
|
||||
export default define(meta, paramDef, async (ps, user) => {
|
||||
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where('note.replyId = :noteId', { noteId: ps.noteId })
|
||||
.orWhere(new Brackets(qb => { qb
|
||||
.where('note.renoteId = :noteId', { noteId: ps.noteId })
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where('note.text IS NOT NULL')
|
||||
.orWhere('note.fileIds != \'{}\'')
|
||||
.orWhere('note.hasPoll = TRUE');
|
||||
}));
|
||||
}));
|
||||
}))
|
||||
.andWhere('note.id IN (SELECT id FROM note_replies(:noteId, :depth, :limit))', { noteId: ps.noteId, depth: ps.depth, limit: ps.limit })
|
||||
.innerJoinAndSelect('note.user', 'user')
|
||||
.leftJoinAndSelect('user.avatar', 'avatar')
|
||||
.leftJoinAndSelect('user.banner', 'banner')
|
||||
|
@ -58,7 +63,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
generateBlockedUserQuery(query, user);
|
||||
}
|
||||
|
||||
const notes = await query.take(ps.limit).getMany();
|
||||
const notes = await query.getMany();
|
||||
|
||||
return await Notes.packMany(notes, user, { detail: false });
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue