Skip to content

Commit d87df0e

Browse files
aster-voidnakaterm
authored andcommitted
recommender を更新する (#575)
ルール: タグと授業のかぶっている数それぞれを合計して、それの降順で並べる。 ## 具体的な変更内容 ## 影響範囲 ## 動作要件 ## 補足 ## レビューリクエストを出す前にチェック! - [ ] 改めてセルフレビューしたか - [ ] 手動での動作検証を行ったか - [ ] server の機能追加ならば、テストを書いたか - 理由: 書いた | server の機能追加ではない - [ ] 間違った使い方が存在するならば、それのドキュメントをコメントで書いたか - 理由: 書いた | 間違った使い方は存在しない - [ ] わかりやすいPRになっているか <!-- レビューリクエスト後は、Slackでもメンションしてお願いすることを推奨します。 -->
1 parent de1468f commit d87df0e

File tree

3 files changed

+25
-30
lines changed

3 files changed

+25
-30
lines changed

server/prisma/sql/recommend.sql

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1-
SELECT recv.id,
2-
(SELECT COUNT(*) FROM "Enrollment" recv_enroll
3-
INNER JOIN "Enrollment" req_enroll
4-
ON recv_enroll."courseId" = req_enroll."courseId"
5-
WHERE recv_enroll."userId" = recv.id
6-
AND req_enroll."userId" = $1)
7-
AS overlap FROM "User" recv
1+
-- $1 = senderId
2+
SELECT
3+
*,
4+
-- course overlap
5+
(SELECT COUNT(1) FROM "Course" course
6+
WHERE EXISTS (SELECT 1 FROM "Enrollment" e WHERE e."courseId" = course.id AND e."userId" = recv.id)
7+
AND EXISTS (SELECT 1 FROM "Enrollment" e WHERE e."courseId" = course.id AND e."userId" = $1)
8+
)
9+
+ -- interest overlap
10+
(SELECT COUNT(1) FROM "InterestSubject" subj
11+
WHERE EXISTS (SELECT 1 FROM "Interest" i WHERE i."subjectId" = subj.id AND i."userId" = recv.id)
12+
AND EXISTS (SELECT 1 FROM "Interest" i WHERE i."subjectId" = subj.id AND i."userId" = $1)
13+
) AS overlap
14+
FROM "User" recv
815
WHERE recv.id <> $1
916

1017
AND NOT EXISTS (
@@ -21,13 +28,3 @@ AND NOT EXISTS (
2128

2229
ORDER BY overlap DESC
2330
LIMIT $2 OFFSET $3;
24-
25-
-- SELECT recv.id AS recv, COUNT(recv_enroll) AS overlap FROM "User" recv
26-
-- LEFT JOIN "Relationship" rel ON (rel."sendingUserId" = recv.id AND rel."receivingUserId" = $1) OR (rel."sendingUserId" = $1 AND rel."sendingUserId" = recv.id)
27-
-- LEFT JOIN "Enrollment" recv_enroll ON recv_enroll."userId" = recv.id
28-
-- INNER JOIN "Course" course ON recv_enroll."courseId" = course.id
29-
-- INNER JOIN "Enrollment" req_enroll ON req_enroll."courseId" = course.id
30-
-- WHERE req_enroll."userId" = $1 AND recv.id <> $1
31-
-- AND rel.status != 'MATCHED'
32-
-- GROUP BY recv.id
33-
-- ORDER BY overlap DESC LIMIT $2 OFFSET $3;

server/src/functions/engines/recommendation.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ beforeAll(() => {
88

99
test("recommendation engine", async () => {
1010
const usersFor101 = await recommendedTo(101, 5, 0);
11-
if (!usersFor101.ok) throw new Error();
11+
if (!usersFor101.ok) throw console.error(usersFor101.error);
1212
expect(usersFor101.value.map((entry) => entry.u.id)).toEqual([102, 103]);
1313

1414
const usersFor102 = await recommendedTo(102, 5, 0);
15-
if (!usersFor102.ok) throw new Error();
15+
if (!usersFor102.ok) throw console.error(usersFor102.error);
1616
expect(usersFor102.value.map((entry) => entry.u.id)).toEqual([103, 101]);
1717

1818
const usersFor103 = await recommendedTo(103, 5, 0);
19-
if (!usersFor103.ok) throw new Error();
19+
if (!usersFor103.ok) throw console.error(usersFor103.error);
2020
expect(usersFor103.value.map((entry) => entry.u.id)).toEqual([102, 101]);
2121
});
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { recommend as sql } from "@prisma/client/sql";
22
import { Err, Ok, type Result } from "common/lib/result";
3-
import type { UserID, UserWithCoursesAndSubjects } from "common/types";
3+
import type { User, UserID, UserWithCoursesAndSubjects } from "common/types";
44
import { prisma } from "../../database/client";
5-
import { getUserByID } from "../../database/users";
65

76
export async function recommendedTo(
87
user: UserID,
@@ -11,7 +10,7 @@ export async function recommendedTo(
1110
): Promise<
1211
Result<
1312
Array<{
14-
u: UserWithCoursesAndSubjects;
13+
u: User; // UserWithCoursesAndSubjects
1514
count: number;
1615
}>
1716
>
@@ -20,17 +19,16 @@ export async function recommendedTo(
2019
const result = await prisma.$queryRawTyped(sql(user, limit, offset));
2120
return Promise.all(
2221
result.map(async (res) => {
23-
const user = await getUserByID(res.id);
24-
if (!user.ok) throw new Error("not found"); // this shouldn't happen
25-
return {
26-
count: Number.parseInt(res.overlap?.toString() ?? "0"),
27-
u: user.value,
28-
};
22+
const { overlap: count, ...u } = res;
23+
if (count === null)
24+
throw new Error("count is null: something is wrong");
25+
return { count: Number(count), u };
2926
}),
3027
)
3128
.then((val) => Ok(val))
3229
.catch((err) => Err(err));
3330
} catch (err) {
34-
return Err(err);
31+
console.error("caught error: ", err);
32+
return Err(500);
3533
}
3634
}

0 commit comments

Comments
 (0)