Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 14 additions & 17 deletions server/prisma/sql/recommend.sql
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
SELECT recv.id,
(SELECT COUNT(*) FROM "Enrollment" recv_enroll
INNER JOIN "Enrollment" req_enroll
ON recv_enroll."courseId" = req_enroll."courseId"
WHERE recv_enroll."userId" = recv.id
AND req_enroll."userId" = $1)
AS overlap FROM "User" recv
-- $1 = senderId
SELECT
*,
-- course overlap
(SELECT COUNT(1) FROM "Course" course
WHERE EXISTS (SELECT 1 FROM "Enrollment" e WHERE e."courseId" = course.id AND e."userId" = recv.id)
AND EXISTS (SELECT 1 FROM "Enrollment" e WHERE e."courseId" = course.id AND e."userId" = $1)
)
+ -- interest overlap
(SELECT COUNT(1) FROM "InterestSubject" subj
WHERE EXISTS (SELECT 1 FROM "Interest" i WHERE i."subjectId" = subj.id AND i."userId" = recv.id)
AND EXISTS (SELECT 1 FROM "Interest" i WHERE i."subjectId" = subj.id AND i."userId" = $1)
) AS overlap
FROM "User" recv
WHERE recv.id <> $1

AND NOT EXISTS (
Expand All @@ -21,13 +28,3 @@ AND NOT EXISTS (

ORDER BY overlap DESC
LIMIT $2 OFFSET $3;

-- SELECT recv.id AS recv, COUNT(recv_enroll) AS overlap FROM "User" recv
-- LEFT JOIN "Relationship" rel ON (rel."sendingUserId" = recv.id AND rel."receivingUserId" = $1) OR (rel."sendingUserId" = $1 AND rel."sendingUserId" = recv.id)
-- LEFT JOIN "Enrollment" recv_enroll ON recv_enroll."userId" = recv.id
-- INNER JOIN "Course" course ON recv_enroll."courseId" = course.id
-- INNER JOIN "Enrollment" req_enroll ON req_enroll."courseId" = course.id
-- WHERE req_enroll."userId" = $1 AND recv.id <> $1
-- AND rel.status != 'MATCHED'
-- GROUP BY recv.id
-- ORDER BY overlap DESC LIMIT $2 OFFSET $3;
6 changes: 3 additions & 3 deletions server/src/functions/engines/recommendation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ beforeAll(() => {

test("recommendation engine", async () => {
const usersFor101 = await recommendedTo(101, 5, 0);
if (!usersFor101.ok) throw new Error();
if (!usersFor101.ok) throw console.error(usersFor101.error);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これ undefined が throw されません?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

テストなので失敗すればなんでもいいかなと思ってこうしました

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

前のだとエラーの情報が消えるので

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど🧐

expect(usersFor101.value.map((entry) => entry.u.id)).toEqual([102, 103]);

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

const usersFor103 = await recommendedTo(103, 5, 0);
if (!usersFor103.ok) throw new Error();
if (!usersFor103.ok) throw console.error(usersFor103.error);
expect(usersFor103.value.map((entry) => entry.u.id)).toEqual([102, 101]);
});
18 changes: 8 additions & 10 deletions server/src/functions/engines/recommendation.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { recommend as sql } from "@prisma/client/sql";
import { Err, Ok, type Result } from "common/lib/result";
import type { UserID, UserWithCoursesAndSubjects } from "common/types";
import type { User, UserID, UserWithCoursesAndSubjects } from "common/types";
import { prisma } from "../../database/client";
import { getUserByID } from "../../database/users";

export async function recommendedTo(
user: UserID,
Expand All @@ -11,7 +10,7 @@ export async function recommendedTo(
): Promise<
Result<
Array<{
u: UserWithCoursesAndSubjects;
u: User; // UserWithCoursesAndSubjects
count: number;
}>
>
Expand All @@ -20,17 +19,16 @@ export async function recommendedTo(
const result = await prisma.$queryRawTyped(sql(user, limit, offset));
return Promise.all(
result.map(async (res) => {
const user = await getUserByID(res.id);
if (!user.ok) throw new Error("not found"); // this shouldn't happen
return {
count: Number.parseInt(res.overlap?.toString() ?? "0"),
u: user.value,
};
const { overlap: count, ...u } = res;
if (count === null)
throw new Error("count is null: something is wrong");
return { count: Number(count), u };
}),
)
.then((val) => Ok(val))
.catch((err) => Err(err));
} catch (err) {
return Err(err);
console.error("caught error: ", err);
return Err(500);
}
}
Loading