diff options
| author | YS <47836716+yszkst@users.noreply.github.com> | 2024-01-15 08:19:27 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-15 08:19:27 +0900 |
| commit | d92aaf81c42dc91a915d38168996536d19d36cf8 (patch) | |
| tree | 5ac23c4d6762713a792a88764e0a92766aa0e873 /packages/backend/src | |
| parent | enhance(frontend) 日本語の拡張絵文字辞書を追加 (#12855) (diff) | |
| download | misskey-d92aaf81c42dc91a915d38168996536d19d36cf8.tar.gz misskey-d92aaf81c42dc91a915d38168996536d19d36cf8.tar.bz2 misskey-d92aaf81c42dc91a915d38168996536d19d36cf8.zip | |
refactor: noteテーブルのインデックス整理と配列カラムへのクエリでインデックスを使うように (#12993)
* Optimize note model index
* enhance(backend): ANY()をやめる (MisskeyIO#239)
* add small e2e test drive endpoint
---------
Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>
Diffstat (limited to 'packages/backend/src')
6 files changed, 16 insertions, 17 deletions
diff --git a/packages/backend/src/core/QueryService.ts b/packages/backend/src/core/QueryService.ts index f006ed4944..13d8a67597 100644 --- a/packages/backend/src/core/QueryService.ts +++ b/packages/backend/src/core/QueryService.ts @@ -212,8 +212,8 @@ export class QueryService { // または 自分自身 .orWhere('note.userId = :meId') // または 自分宛て - .orWhere(':meId = ANY(note.visibleUserIds)') - .orWhere(':meId = ANY(note.mentions)') + .orWhere(':meIdAsList <@ note.visibleUserIds') + .orWhere(':meIdAsList <@ note.mentions') .orWhere(new Brackets(qb => { qb // または フォロワー宛ての投稿であり、 @@ -228,7 +228,7 @@ export class QueryService { })); })); - q.setParameters({ meId: me.id }); + q.setParameters({ meId: me.id, meIdAsList: [me.id] }); } } diff --git a/packages/backend/src/models/Note.ts b/packages/backend/src/models/Note.ts index a4358b9ba6..dee2560b7c 100644 --- a/packages/backend/src/models/Note.ts +++ b/packages/backend/src/models/Note.ts @@ -11,9 +11,6 @@ import { MiChannel } from './Channel.js'; import type { MiDriveFile } from './DriveFile.js'; @Entity('note') -@Index('IDX_NOTE_TAGS', { synchronize: false }) -@Index('IDX_NOTE_MENTIONS', { synchronize: false }) -@Index('IDX_NOTE_VISIBLE_USER_IDS', { synchronize: false }) export class MiNote { @PrimaryColumn(id()) public id: string; @@ -133,7 +130,7 @@ export class MiNote { }) public url: string | null; - @Index() + @Index('IDX_NOTE_FILE_IDS', { synchronize: false }) @Column({ ...id(), array: true, default: '{}', @@ -145,14 +142,14 @@ export class MiNote { }) public attachedFileTypes: string[]; - @Index() + @Index('IDX_NOTE_VISIBLE_USER_IDS', { synchronize: false }) @Column({ ...id(), array: true, default: '{}', }) public visibleUserIds: MiUser['id'][]; - @Index() + @Index('IDX_NOTE_MENTIONS', { synchronize: false }) @Column({ ...id(), array: true, default: '{}', @@ -174,7 +171,7 @@ export class MiNote { }) public emojis: string[]; - @Index() + @Index('IDX_NOTE_TAGS', { synchronize: false }) @Column('varchar', { length: 128, array: true, default: '{}', }) diff --git a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts index 14a13b09c9..7a0b8b4417 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts @@ -74,7 +74,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- } const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId); - query.andWhere(':file = ANY(note.fileIds)', { file: file.id }); + query.andWhere(':file <@ note.fileIds', { file: [file.id] }); const notes = await query.limit(ps.limit).getMany(); diff --git a/packages/backend/src/server/api/endpoints/hashtags/users.ts b/packages/backend/src/server/api/endpoints/hashtags/users.ts index 50aea79943..8302d2380f 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/users.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/users.ts @@ -6,6 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { UsersRepository } from '@/models/_.js'; +import { safeForSql } from "@/misc/safe-for-sql.js"; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; @@ -47,8 +48,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- private userEntityService: UserEntityService, ) { super(meta, paramDef, async (ps, me) => { + if (!safeForSql(normalizeForSearch(ps.tag))) throw new Error('Injection'); const query = this.usersRepository.createQueryBuilder('user') - .where(':tag = ANY(user.tags)', { tag: normalizeForSearch(ps.tag) }) + .where(':tag <@ user.tags', { tag: [normalizeForSearch(ps.tag)] }) .andWhere('user.isSuspended = FALSE'); const recent = new Date(Date.now() - (1000 * 60 * 60 * 24 * 5)); diff --git a/packages/backend/src/server/api/endpoints/notes/mentions.ts b/packages/backend/src/server/api/endpoints/notes/mentions.ts index 2317f8f7b2..323c6c946b 100644 --- a/packages/backend/src/server/api/endpoints/notes/mentions.ts +++ b/packages/backend/src/server/api/endpoints/notes/mentions.ts @@ -61,9 +61,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId) .andWhere(new Brackets(qb => { - qb - .where(`'{"${me.id}"}' <@ note.mentions`) - .orWhere(`'{"${me.id}"}' <@ note.visibleUserIds`); + qb // このmeIdAsListパラメータはqueryServiceのgenerateVisibilityQueryでセットされる + .where(':meIdAsList <@ note.mentions') + .orWhere(':meIdAsList <@ note.visibleUserIds'); })) // Avoid scanning primary key index .orderBy('CONCAT(note.id)', 'DESC') diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts index b00f5207d8..0d7aca6621 100644 --- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts +++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts @@ -87,14 +87,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- try { if (ps.tag) { if (!safeForSql(normalizeForSearch(ps.tag))) throw new Error('Injection'); - query.andWhere(`'{"${normalizeForSearch(ps.tag)}"}' <@ note.tags`); + query.andWhere(':tag <@ note.tags', { tag: [normalizeForSearch(ps.tag)] }); } else { query.andWhere(new Brackets(qb => { for (const tags of ps.query!) { qb.orWhere(new Brackets(qb => { for (const tag of tags) { if (!safeForSql(normalizeForSearch(tag))) throw new Error('Injection'); - qb.andWhere(`'{"${normalizeForSearch(tag)}"}' <@ note.tags`); + qb.andWhere(':tag <@ note.tags', { tag: [normalizeForSearch(tag)] }); } })); } |