server/utils/meilisearch.ts

173 lines
4.9 KiB
TypeScript
Raw Normal View History

2024-04-07 07:30:49 +02:00
import chalk from "chalk";
2024-04-07 06:16:54 +02:00
import { config } from "config-manager";
2024-04-13 14:24:57 +02:00
import { count } from "drizzle-orm";
import { LogLevel, type LogManager, type MultiLogManager } from "log-manager";
2024-04-07 07:30:49 +02:00
import { Meilisearch } from "meilisearch";
import { db } from "~/drizzle/db";
import { Notes, Users } from "~/drizzle/schema";
import type { User } from "~/packages/database-interface/user";
export const meilisearch = new Meilisearch({
2024-04-07 07:30:49 +02:00
host: `${config.meilisearch.host}:${config.meilisearch.port}`,
apiKey: config.meilisearch.api_key,
});
export const connectMeili = async (logger: MultiLogManager | LogManager) => {
2024-04-07 07:30:49 +02:00
if (!config.meilisearch.enabled) return;
if (await meilisearch.isHealthy()) {
await meilisearch
.index(MeiliIndexType.Accounts)
.updateSortableAttributes(["createdAt"]);
await meilisearch
.index(MeiliIndexType.Accounts)
.updateSearchableAttributes(["username", "displayName", "note"]);
await meilisearch
.index(MeiliIndexType.Statuses)
.updateSortableAttributes(["createdAt"]);
await meilisearch
.index(MeiliIndexType.Statuses)
.updateSearchableAttributes(["content"]);
await logger.log(
LogLevel.INFO,
"Meilisearch",
"Connected to Meilisearch",
);
} else {
await logger.log(
LogLevel.CRITICAL,
"Meilisearch",
"Error while connecting to Meilisearch",
);
process.exit(1);
}
};
2023-12-03 05:40:10 +01:00
export enum MeiliIndexType {
2024-04-07 07:30:49 +02:00
Accounts = "accounts",
Statuses = "statuses",
}
export const addUserToMeilisearch = async (user: User) => {
2024-04-07 07:30:49 +02:00
if (!config.meilisearch.enabled) return;
await meilisearch.index(MeiliIndexType.Accounts).addDocuments([
{
id: user.id,
username: user.data.username,
displayName: user.data.displayName,
note: user.data.note,
createdAt: user.data.createdAt,
2024-04-07 07:30:49 +02:00
},
]);
};
export const getNthDatabaseAccountBatch = (
2024-04-07 07:30:49 +02:00
n: number,
batchSize = 1000,
2023-12-03 05:40:10 +01:00
): Promise<Record<string, string | Date>[]> => {
return db.query.Users.findMany({
2024-04-13 14:24:57 +02:00
offset: n * batchSize,
limit: batchSize,
columns: {
2024-04-07 07:30:49 +02:00
id: true,
username: true,
displayName: true,
note: true,
createdAt: true,
},
2024-04-13 14:24:57 +02:00
orderBy: (user, { asc }) => asc(user.createdAt),
2024-04-07 07:30:49 +02:00
});
};
export const getNthDatabaseStatusBatch = (
2024-04-07 07:30:49 +02:00
n: number,
batchSize = 1000,
2023-12-03 05:40:10 +01:00
): Promise<Record<string, string | Date>[]> => {
return db.query.Notes.findMany({
2024-04-13 14:24:57 +02:00
offset: n * batchSize,
limit: batchSize,
columns: {
2024-04-07 07:30:49 +02:00
id: true,
content: true,
createdAt: true,
},
2024-04-13 14:24:57 +02:00
orderBy: (status, { asc }) => asc(status.createdAt),
2024-04-07 07:30:49 +02:00
});
};
export const rebuildSearchIndexes = async (
2024-04-07 07:30:49 +02:00
indexes: MeiliIndexType[],
batchSize = 100,
) => {
2024-04-07 07:30:49 +02:00
if (indexes.includes(MeiliIndexType.Accounts)) {
2024-04-13 14:24:57 +02:00
const accountCount = (
await db
.select({
count: count(),
})
.from(Users)
2024-04-13 14:24:57 +02:00
)[0].count;
2024-04-07 07:30:49 +02:00
for (let i = 0; i < accountCount / batchSize; i++) {
const accounts = await getNthDatabaseAccountBatch(i, batchSize);
2024-04-07 07:30:49 +02:00
const progress = Math.round((i / (accountCount / batchSize)) * 100);
2024-04-07 07:30:49 +02:00
console.log(`${chalk.green("✓")} ${progress}%`);
2024-04-07 07:30:49 +02:00
// Sync with Meilisearch
await meilisearch
.index(MeiliIndexType.Accounts)
.addDocuments(accounts);
}
2024-04-07 07:30:49 +02:00
const meiliAccountCount = (
await meilisearch.index(MeiliIndexType.Accounts).getStats()
).numberOfDocuments;
2024-04-07 07:30:49 +02:00
console.log(
`${chalk.green("✓")} ${chalk.bold(
`Done! ${meiliAccountCount} accounts indexed`,
)}`,
);
}
2024-04-07 07:30:49 +02:00
if (indexes.includes(MeiliIndexType.Statuses)) {
2024-04-13 14:24:57 +02:00
const statusCount = (
await db
.select({
count: count(),
})
.from(Notes)
2024-04-13 14:24:57 +02:00
)[0].count;
2024-04-07 07:30:49 +02:00
for (let i = 0; i < statusCount / batchSize; i++) {
const statuses = await getNthDatabaseStatusBatch(i, batchSize);
2024-04-07 07:30:49 +02:00
const progress = Math.round((i / (statusCount / batchSize)) * 100);
2024-04-07 07:30:49 +02:00
console.log(`${chalk.green("✓")} ${progress}%`);
2024-04-07 07:30:49 +02:00
// Sync with Meilisearch
await meilisearch
.index(MeiliIndexType.Statuses)
.addDocuments(statuses);
}
2024-04-07 07:30:49 +02:00
const meiliStatusCount = (
await meilisearch.index(MeiliIndexType.Statuses).getStats()
).numberOfDocuments;
2023-12-03 05:40:10 +01:00
2024-04-07 07:30:49 +02:00
console.log(
`${chalk.green("✓")} ${chalk.bold(
`Done! ${meiliStatusCount} statuses indexed`,
)}`,
);
}
};