summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2021-03-20 13:54:59 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2021-03-20 13:54:59 +0900
commitf27e4033a6599203ba37efe01edbd988699b4068 (patch)
tree39249a742055a53c9690f89fdbef8980e48fe01b /src
parentperf(server): Reduce database query (diff)
downloadmisskey-f27e4033a6599203ba37efe01edbd988699b4068.tar.gz
misskey-f27e4033a6599203ba37efe01edbd988699b4068.tar.bz2
misskey-f27e4033a6599203ba37efe01edbd988699b4068.zip
perf(server): Reduce database query
Related: #6813
Diffstat (limited to 'src')
-rw-r--r--src/models/repositories/note.ts86
-rw-r--r--src/models/repositories/notification.ts45
-rw-r--r--src/models/repositories/user.ts40
-rw-r--r--src/server/api/endpoints/antennas/notes.ts4
-rw-r--r--src/server/api/endpoints/channels/timeline.ts4
-rw-r--r--src/server/api/endpoints/clips/notes.ts4
-rw-r--r--src/server/api/endpoints/i/notifications.ts6
-rw-r--r--src/server/api/endpoints/notes.ts6
-rw-r--r--src/server/api/endpoints/notes/children.ts6
-rw-r--r--src/server/api/endpoints/notes/featured.ts6
-rw-r--r--src/server/api/endpoints/notes/global-timeline.ts6
-rw-r--r--src/server/api/endpoints/notes/hybrid-timeline.ts4
-rw-r--r--src/server/api/endpoints/notes/local-timeline.ts6
-rw-r--r--src/server/api/endpoints/notes/mentions.ts6
-rw-r--r--src/server/api/endpoints/notes/renotes.ts6
-rw-r--r--src/server/api/endpoints/notes/replies.ts6
-rw-r--r--src/server/api/endpoints/notes/search-by-tag.ts6
-rw-r--r--src/server/api/endpoints/notes/search.ts6
-rw-r--r--src/server/api/endpoints/notes/timeline.ts4
-rw-r--r--src/server/api/endpoints/notes/user-list-timeline.ts4
-rw-r--r--src/server/api/endpoints/users/notes.ts6
21 files changed, 240 insertions, 27 deletions
diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts
index 43caaf94b2..1fcedbd56f 100644
--- a/src/models/repositories/note.ts
+++ b/src/models/repositories/note.ts
@@ -85,6 +85,7 @@ export class NoteRepository extends Repository<Note> {
detail?: boolean;
skipHide?: boolean;
_hint_?: {
+ emojis: Emoji[] | null;
myReactions: Map<Note['id'], NoteReaction | null>;
};
}
@@ -141,11 +142,43 @@ export class NoteRepository extends Repository<Note> {
* @param reactionNames Note等にリアクションされたカスタム絵文字名 (:は含めない)
*/
async function populateEmojis(emojiNames: string[], noteUserHost: string | null, reactionNames: string[]) {
+ const customReactions = reactionNames?.map(x => decodeReaction(x)).filter(x => x.name);
+
let all = [] as {
name: string,
url: string
}[];
+ // 与えられたhintだけで十分(=新たにクエリする必要がない)かどうかを表すフラグ
+ let enough = true;
+ if (options?._hint_?.emojis) {
+ for (const name of emojiNames) {
+ const matched = options._hint_.emojis.find(x => x.name === name && x.host === noteUserHost);
+ if (matched) {
+ all.push({
+ name: matched.name,
+ url: matched.url,
+ });
+ } else {
+ enough = false;
+ }
+ }
+ for (const customReaction of customReactions) {
+ const matched = options._hint_.emojis.find(x => x.name === customReaction.name && x.host === customReaction.host);
+ if (matched) {
+ all.push({
+ name: `${matched.name}@${matched.host || '.'}`, // @host付きでローカルは.
+ url: matched.url,
+ });
+ } else {
+ enough = false;
+ }
+ }
+ } else {
+ enough = false;
+ }
+ if (enough) return all;
+
// カスタム絵文字
if (emojiNames?.length > 0) {
const tmp = await Emojis.find({
@@ -164,8 +197,6 @@ export class NoteRepository extends Repository<Note> {
all = concat([all, tmp]);
}
- const customReactions = reactionNames?.map(x => decodeReaction(x)).filter(x => x.name);
-
if (customReactions?.length > 0) {
const where = [] as {}[];
@@ -230,7 +261,12 @@ export class NoteRepository extends Repository<Note> {
id: note.id,
createdAt: note.createdAt.toISOString(),
userId: note.userId,
- user: Users.pack(note.user || note.userId, meId),
+ user: Users.pack(note.user || note.userId, meId, {
+ detail: false,
+ _hint_: {
+ emojis: options?._hint_?.emojis || null
+ }
+ }),
text: text,
cw: note.cw,
visibility: note.visibility,
@@ -258,12 +294,12 @@ export class NoteRepository extends Repository<Note> {
_prId_: (note as any)._prId_ || undefined,
...(opts.detail ? {
- reply: note.replyId ? this.pack(note.replyId, meId, {
+ reply: note.replyId ? this.pack(note.reply || note.replyId, meId, {
detail: false,
_hint_: options?._hint_
}) : undefined,
- renote: note.renoteId ? this.pack(note.renoteId, meId, {
+ renote: note.renoteId ? this.pack(note.renote || note.renoteId, meId, {
detail: true,
_hint_: options?._hint_
}) : undefined,
@@ -314,10 +350,48 @@ export class NoteRepository extends Repository<Note> {
}
}
+ // TODO: ここら辺の処理をaggregateEmojisみたいな関数に切り出したい
+ let emojisWhere: any[] = [];
+ for (const note of notes) {
+ if (typeof note !== 'object') continue;
+ emojisWhere.push({
+ name: In(note.emojis),
+ host: note.userHost
+ });
+ if (note.renote) {
+ emojisWhere.push({
+ name: In(note.renote.emojis),
+ host: note.renote.userHost
+ });
+ if (note.renote.user) {
+ emojisWhere.push({
+ name: In(note.renote.user.emojis),
+ host: note.renote.userHost
+ });
+ }
+ }
+ const customReactions = Object.keys(note.reactions).map(x => decodeReaction(x)).filter(x => x.name);
+ emojisWhere = emojisWhere.concat(customReactions.map(x => ({
+ name: x.name,
+ host: x.host
+ })));
+ if (note.user) {
+ emojisWhere.push({
+ name: In(note.user.emojis),
+ host: note.userHost
+ });
+ }
+ }
+ const emojis = emojisWhere.length > 0 ? await Emojis.find({
+ where: emojisWhere,
+ select: ['name', 'host', 'url']
+ }) : null;
+
return await Promise.all(notes.map(n => this.pack(n, me, {
...options,
_hint_: {
- myReactions: myReactionsMap
+ myReactions: myReactionsMap,
+ emojis: emojis
}
})));
}
diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts
index a9fe5e7b4e..1027155873 100644
--- a/src/models/repositories/notification.ts
+++ b/src/models/repositories/notification.ts
@@ -1,11 +1,13 @@
import { EntityRepository, In, Repository } from 'typeorm';
-import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions } from '..';
+import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions, Emojis } from '..';
import { Notification } from '../entities/notification';
import { awaitAll } from '../../prelude/await-all';
import { SchemaType } from '../../misc/schema';
import { Note } from '../entities/note';
import { NoteReaction } from '../entities/note-reaction';
import { User } from '../entities/user';
+import { decodeReaction } from '../../misc/reaction-lib';
+import { Emoji } from '../entities/emoji';
export type PackedNotification = SchemaType<typeof packedNotificationSchema>;
@@ -15,6 +17,7 @@ export class NotificationRepository extends Repository<Notification> {
src: Notification['id'] | Notification,
options: {
_hintForEachNotes_: {
+ emojis: Emoji[] | null;
myReactions: Map<Note['id'], NoteReaction | null>;
};
}
@@ -98,9 +101,47 @@ export class NotificationRepository extends Repository<Notification> {
myReactionsMap.set(target, myReactions.find(reaction => reaction.noteId === target) || null);
}
+ // TODO: ここら辺の処理をaggregateEmojisみたいな関数に切り出したい
+ let emojisWhere: any[] = [];
+ for (const note of notes) {
+ if (typeof note !== 'object') continue;
+ emojisWhere.push({
+ name: In(note.emojis),
+ host: note.userHost
+ });
+ if (note.renote) {
+ emojisWhere.push({
+ name: In(note.renote.emojis),
+ host: note.renote.userHost
+ });
+ if (note.renote.user) {
+ emojisWhere.push({
+ name: In(note.renote.user.emojis),
+ host: note.renote.userHost
+ });
+ }
+ }
+ const customReactions = Object.keys(note.reactions).map(x => decodeReaction(x)).filter(x => x.name);
+ emojisWhere = emojisWhere.concat(customReactions.map(x => ({
+ name: x.name,
+ host: x.host
+ })));
+ if (note.user) {
+ emojisWhere.push({
+ name: In(note.user.emojis),
+ host: note.userHost
+ });
+ }
+ }
+ const emojis = emojisWhere.length > 0 ? await Emojis.find({
+ where: emojisWhere,
+ select: ['name', 'host', 'url']
+ }) : null;
+
return await Promise.all(notifications.map(x => this.pack(x, {
_hintForEachNotes_: {
- myReactions: myReactionsMap
+ myReactions: myReactionsMap,
+ emojis: emojis,
}
})));
}
diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts
index 3a6ab48c5f..19b0e54239 100644
--- a/src/models/repositories/user.ts
+++ b/src/models/repositories/user.ts
@@ -5,6 +5,7 @@ import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMes
import config from '../../config';
import { SchemaType } from '../../misc/schema';
import { awaitAll } from '../../prelude/await-all';
+import { Emoji } from '../entities/emoji';
export type PackedUser = SchemaType<typeof packedUserSchema>;
@@ -149,6 +150,9 @@ export class UserRepository extends Repository<User> {
options?: {
detail?: boolean,
includeSecrets?: boolean,
+ _hint_?: {
+ emojis: Emoji[] | null;
+ };
}
): Promise<PackedUser> {
const opts = Object.assign({
@@ -166,6 +170,34 @@ export class UserRepository extends Repository<User> {
}) : [];
const profile = opts.detail ? await UserProfiles.findOneOrFail(user.id) : null;
+ let emojis: Emoji[] = [];
+ if (user.emojis.length > 0) {
+ // 与えられたhintだけで十分(=新たにクエリする必要がない)かどうかを表すフラグ
+ let enough = true;
+ if (options?._hint_?.emojis) {
+ for (const name of user.emojis) {
+ const matched = options._hint_.emojis.find(x => x.name === name && x.host === user.host);
+ if (matched) {
+ emojis.push(matched);
+ } else {
+ enough = false;
+ }
+ }
+ } else {
+ enough = false;
+ }
+
+ if (!enough) {
+ emojis = await Emojis.find({
+ where: {
+ name: In(user.emojis),
+ host: user.host
+ },
+ select: ['name', 'host', 'url', 'aliases']
+ });
+ }
+ }
+
const falsy = opts.detail ? false : undefined;
const packed = {
@@ -190,13 +222,7 @@ export class UserRepository extends Repository<User> {
} : undefined) : undefined,
// カスタム絵文字添付
- emojis: user.emojis.length > 0 ? Emojis.find({
- where: {
- name: In(user.emojis),
- host: user.host
- },
- select: ['name', 'host', 'url', 'aliases']
- }) : [],
+ emojis: emojis,
...(opts.detail ? {
url: profile!.url,
diff --git a/src/server/api/endpoints/antennas/notes.ts b/src/server/api/endpoints/antennas/notes.ts
index 750fc080cf..2ea3e43745 100644
--- a/src/server/api/endpoints/antennas/notes.ts
+++ b/src/server/api/endpoints/antennas/notes.ts
@@ -74,6 +74,10 @@ export default define(meta, async (ps, user) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere(`note.id IN (${ antennaQuery.getQuery() })`)
.leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
.setParameters(antennaQuery.getParameters());
generateVisibilityQuery(query, user);
diff --git a/src/server/api/endpoints/channels/timeline.ts b/src/server/api/endpoints/channels/timeline.ts
index acb34f124d..292f21b63d 100644
--- a/src/server/api/endpoints/channels/timeline.ts
+++ b/src/server/api/endpoints/channels/timeline.ts
@@ -88,6 +88,10 @@ export default define(meta, async (ps, user) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('note.channelId = :channelId', { channelId: channel.id })
.leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
.leftJoinAndSelect('note.channel', 'channel');
//#endregion
diff --git a/src/server/api/endpoints/clips/notes.ts b/src/server/api/endpoints/clips/notes.ts
index 6a507e2036..86d1e507f4 100644
--- a/src/server/api/endpoints/clips/notes.ts
+++ b/src/server/api/endpoints/clips/notes.ts
@@ -72,6 +72,10 @@ export default define(meta, async (ps, user) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere(`note.id IN (${ clipQuery.getQuery() })`)
.leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
.setParameters(clipQuery.getParameters());
if (user) {
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index af49549d37..812a4bd1dd 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -87,7 +87,11 @@ export default define(meta, async (ps, user) => {
.andWhere(`notification.notifieeId = :meId`, { meId: user.id })
.leftJoinAndSelect('notification.notifier', 'notifier')
.leftJoinAndSelect('notification.note', 'note')
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
query.andWhere(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`);
query.setParameters(mutingQuery.getParameters());
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
index fab8455d78..708ce38c0e 100644
--- a/src/server/api/endpoints/notes.ts
+++ b/src/server/api/endpoints/notes.ts
@@ -76,7 +76,11 @@ export default define(meta, async (ps) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere(`note.visibility = 'public'`)
.andWhere(`note.localOnly = FALSE`)
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
if (ps.local) {
query.andWhere('note.userHost IS NULL');
diff --git a/src/server/api/endpoints/notes/children.ts b/src/server/api/endpoints/notes/children.ts
index 0875e0f240..a8b239e445 100644
--- a/src/server/api/endpoints/notes/children.ts
+++ b/src/server/api/endpoints/notes/children.ts
@@ -64,7 +64,11 @@ export default define(meta, async (ps, user) => {
}));
}));
}))
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateVisibilityQuery(query, user);
if (user) generateMutedUserQuery(query, user);
diff --git a/src/server/api/endpoints/notes/featured.ts b/src/server/api/endpoints/notes/featured.ts
index 4dda7d0edb..6c416b1c04 100644
--- a/src/server/api/endpoints/notes/featured.ts
+++ b/src/server/api/endpoints/notes/featured.ts
@@ -49,7 +49,11 @@ export default define(meta, async (ps, user) => {
.andWhere(`note.score > 0`)
.andWhere(`note.createdAt > :date`, { date: new Date(Date.now() - day) })
.andWhere(`note.visibility = 'public'`)
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
if (user) generateMutedUserQuery(query, user);
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index 6d99f1fdbc..64c2f5851c 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -81,7 +81,11 @@ export default define(meta, async (ps, user) => {
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('note.visibility = \'public\'')
.andWhere('note.channelId IS NULL')
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateRepliesQuery(query, user);
if (user) generateMutedUserQuery(query, user);
diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts
index 2b91b8c67b..c01e170aa9 100644
--- a/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -130,6 +130,10 @@ export default define(meta, async (ps, user) => {
.orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)');
}))
.leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
.setParameters(followingQuery.getParameters());
generateChannelQuery(query, user);
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index 51e35e6241..31abb26882 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -98,7 +98,11 @@ export default define(meta, async (ps, user) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'),
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)')
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateChannelQuery(query, user);
generateRepliesQuery(query, user);
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 1e3014bd46..83e890d9ad 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -63,7 +63,11 @@ export default define(meta, async (ps, user) => {
.where(`:meId = ANY(note.mentions)`, { meId: user.id })
.orWhere(`:meId = ANY(note.visibleUserIds)`, { meId: user.id });
}))
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateVisibilityQuery(query, user);
generateMutedUserQuery(query, user);
diff --git a/src/server/api/endpoints/notes/renotes.ts b/src/server/api/endpoints/notes/renotes.ts
index 31c24f294a..f528197220 100644
--- a/src/server/api/endpoints/notes/renotes.ts
+++ b/src/server/api/endpoints/notes/renotes.ts
@@ -68,7 +68,11 @@ export default define(meta, async (ps, user) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere(`note.renoteId = :renoteId`, { renoteId: note.id })
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateVisibilityQuery(query, user);
if (user) generateMutedUserQuery(query, user);
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 9fad74c78e..5ac663d77a 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -59,7 +59,11 @@ export const meta = {
export default define(meta, async (ps, user) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere('note.replyId = :replyId', { replyId: ps.noteId })
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateVisibilityQuery(query, user);
if (user) generateMutedUserQuery(query, user);
diff --git a/src/server/api/endpoints/notes/search-by-tag.ts b/src/server/api/endpoints/notes/search-by-tag.ts
index e0f7f4d62c..d878f379c3 100644
--- a/src/server/api/endpoints/notes/search-by-tag.ts
+++ b/src/server/api/endpoints/notes/search-by-tag.ts
@@ -95,7 +95,11 @@ export const meta = {
export default define(meta, async (ps, me) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateVisibilityQuery(query, me);
if (me) generateMutedUserQuery(query, me);
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
index 1aca056299..ae0e9242a6 100644
--- a/src/server/api/endpoints/notes/search.ts
+++ b/src/server/api/endpoints/notes/search.ts
@@ -79,7 +79,11 @@ export default define(meta, async (ps, me) => {
query
.andWhere('note.text ILIKE :q', { q: `%${ps.query}%` })
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateVisibilityQuery(query, me);
if (me) generateMutedUserQuery(query, me);
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index f09f3d1733..c91bea0c1f 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -123,6 +123,10 @@ export default define(meta, async (ps, user) => {
if (hasFollowing) qb.orWhere(`note.userId IN (${ followingQuery.getQuery() })`);
}))
.leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
.setParameters(followingQuery.getParameters());
generateChannelQuery(query, user);
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
index b0ff499d95..040f017fd5 100644
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -131,6 +131,10 @@ export default define(meta, async (ps, user) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
.andWhere(`note.userId IN (${ listQuery.getQuery() })`)
.leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
.setParameters(listQuery.getParameters());
generateVisibilityQuery(query, user);
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
index 33e3ecb03f..91d1d7f4dd 100644
--- a/src/server/api/endpoints/users/notes.ts
+++ b/src/server/api/endpoints/users/notes.ts
@@ -131,7 +131,11 @@ export default define(meta, async (ps, me) => {
//#region Construct query
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
.andWhere('note.userId = :userId', { userId: user.id })
- .leftJoinAndSelect('note.user', 'user');
+ .leftJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser');
generateVisibilityQuery(query, me);
if (me) generateMutedUserQuery(query, me, user);