feat: use PGroonga for full-text search

Co-authored-by: tamaina <tamaina@hotmail.co.jp>
This commit is contained in:
naskya 2023-10-28 20:19:25 +09:00
parent 182882f61d
commit 624f31ffaf
Signed by: naskya
GPG key ID: 164DFF24E2D40139
12 changed files with 149 additions and 44 deletions
packages/backend
migration-neko
src
models/entities
server/api/endpoints

View file

@ -0,0 +1,27 @@
export class Pgroonga1698420787202 {
name = "Pgroonga1698420787202";
async up(queryRunner) {
await queryRunner.query(
`CREATE INDEX "IDX_f27f5d88941e57442be75ba9c8" ON "note" USING "pgroonga" ("text")`,
);
await queryRunner.query(
`CREATE INDEX "IDX_065d4d8f3b5adb4a08841eae3c" ON "user" USING "pgroonga" ("name" pgroonga_varchar_full_text_search_ops_v2)`,
);
await queryRunner.query(
`CREATE INDEX "IDX_fcb770976ff8240af5799e3ffc" ON "user_profile" USING "pgroonga" ("description" pgroonga_varchar_full_text_search_ops_v2) `,
);
}
async down(queryRunner) {
await queryRunner.query(
`DROP INDEX "public"."IDX_fcb770976ff8240af5799e3ffc"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_065d4d8f3b5adb4a08841eae3c"`,
);
await queryRunner.query(
`DROP INDEX "public"."IDX_f27f5d88941e57442be75ba9c8"`,
);
}
}

View file

@ -61,6 +61,7 @@ export class Note {
})
public threadId: string | null;
@Index() // USING pgroonga
@Column("text", {
nullable: true,
})

View file

@ -38,6 +38,7 @@ export class UserProfile {
})
public birthday: string | null;
@Index() // USING pgroonga pgroonga_varchar_full_text_search_ops_v2
@Column("varchar", {
length: 2048,
nullable: true,

View file

@ -64,6 +64,7 @@ export class User {
})
public usernameLower: string;
@Index() // USING pgroonga pgroonga_varchar_full_text_search_ops_v2
@Column("varchar", {
length: 128,
nullable: true,

View file

@ -91,7 +91,7 @@ export default define(meta, paramDef, async (ps, me) => {
}
query
.andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(ps.query)}%` })
.andWhere("note.text &@~ :q", { q: `${sqlLikeEscape(ps.query)}` })
.andWhere("note.visibility = 'public'")
.innerJoinAndSelect("note.user", "user")
.leftJoinAndSelect("user.avatar", "avatar")

View file

@ -78,8 +78,8 @@ export default define(meta, paramDef, async (ps, me) => {
const nameQuery = Users.createQueryBuilder("user")
.where(
new Brackets((qb) => {
qb.where("user.name ILIKE :query", {
query: `%${sqlLikeEscape(ps.query)}%`,
qb.where("user.name &@~ :query", {
query: `${sqlLikeEscape(ps.query)}`,
});
// Also search username if it qualifies as username
@ -115,8 +115,8 @@ export default define(meta, paramDef, async (ps, me) => {
if (users.length < ps.limit) {
const profQuery = UserProfiles.createQueryBuilder("prof")
.select("prof.userId")
.where("prof.description ILIKE :query", {
query: `%${sqlLikeEscape(ps.query)}%`,
.where("prof.description &@~ :query", {
query: `${sqlLikeEscape(ps.query)}`,
});
if (ps.origin === "local") {