Subset์ Model์ ๋ฉ์๋๋ฅผ ํตํด ์ฌ์ฉํฉ๋๋ค.
Model ๋ฉ์๋์ Subset
findById - ๋จ์ผ ๋ ์ฝ๋ ์กฐํ
// Subset 1๊ฐ
const user = await UserModel.findById(1, ["P"]);
// ํ์
: UserSubsetMapping["P"]
// Subset ์ฌ๋ฌ ๊ฐ (Union)
const user = await UserModel.findById(1, ["A", "P"]);
// ํ์
: UserSubsetMapping["A"] | UserSubsetMapping["P"]
findOne - ์กฐ๊ฑด์ผ๋ก ๋จ์ผ ๋ ์ฝ๋
const user = await UserModel.findOne({
where: [["email", "[email protected]"]],
subsetKey: "P",
});
// ํ์
: UserSubsetMapping["P"] | undefined
findMany - ์ฌ๋ฌ ๋ ์ฝ๋ ์กฐํ
const users = await UserModel.findMany({
listParams: {
page: 1,
pageSize: 20,
},
subsetKey: "L",
});
// ํ์
: UserSubsetMapping["L"][]
getPuri๋ก Subset ์ฟผ๋ฆฌ ์์
getPuri๋ฅผ ์ฌ์ฉํ์ฌ Subset ๊ธฐ๋ฐ ์ฟผ๋ฆฌ๋ฅผ ์์ํฉ๋๋ค:
// Subset P์ ์ฟผ๋ฆฌ ์์
const query = UserModel.getPuri("r", ["P"]);
// ์ถ๊ฐ ์กฐ๊ฑด ์ ์ฉ
const users = await query
.where("users.role", "admin")
.where("users.is_verified", true)
.orderBy("users.created_at", "desc");
// ํ์
: UserSubsetMapping["P"][]
getPuri("r", ["P"])๋ Subset P์ ์ ์๋ JOIN๊ณผ SELECT๋ฅผ ์๋์ผ๋ก ์ ์ฉํฉ๋๋ค.
Subset ์ฟผ๋ฆฌ ํ์ฅ
WHERE ์กฐ๊ฑด ์ถ๊ฐ
const admins = await UserModel.getPuri("r", ["L"])
.where("users.role", "admin")
.where("users.is_verified", true);
// Subset L์ ๊ธฐ๋ณธ ํ๋ + WHERE ์กฐ๊ฑด
ORDER BY ์ ๋ ฌ
const recentUsers = await UserModel.getPuri("r", ["L"])
.orderBy("users.created_at", "desc")
.limit(10);
๋ณตํฉ ์กฐ๊ฑด
const activeEngineers = await UserModel.getPuri("r", ["P"])
.where("users.role", "normal")
.where("employee__department.name", "Engineering")
.where("employee.salary", ">", "60000")
.orderBy("employee.salary", "desc");
// Subset P๋ employee.department.name์ ํฌํจํ๋ฏ๋ก
// JOIN์ด ์๋์ผ๋ก ์ค์ ๋จ
Subset ํ์
์์ ์ฑ
์ปดํ์ผ ํ์ ๊ฒ์ฆ
// โ
OK: Subset P๋ employee__department ํ
์ด๋ธ ํฌํจ
await UserModel.getPuri("r", ["P"])
.where("employee__department.name", "Engineering");
// โ Type Error: Subset L์ employee ํ
์ด๋ธ ๋ฏธํฌํจ
await UserModel.getPuri("r", ["L"])
.where("employee__department.name", "Engineering");
// ^^^^^^^^^^^^^^^^^^^^^^^^^ Property does not exist
์๋ ํ์
์ถ๋ก
const user = await UserModel.findById(1, ["P"]);
// TypeScript๊ฐ ์๋์ผ๋ก ํ์
์ถ๋ก
user.id; // number
user.username; // string
user.employee; // { salary: string; department: { name: string } } | null
// โ Compile Error
user.password; // Property 'password' does not exist
์ค์ ์์
์ฌ์ฉ์ ๋ชฉ๋ก API
// Controller
class UserController {
async list(req: TypedRequest<UserListParams>) {
const { page, pageSize, role, search } = req.body;
let query = UserModel.getPuri("r", ["L"]);
// ์ญํ ํํฐ
if (role) {
query = query.where("users.role", role);
}
// ๊ฒ์
if (search) {
query = query.where("users.username", "like", `%${search}%`);
}
const users = await query
.orderBy("users.created_at", "desc")
.limit(pageSize)
.offset((page - 1) * pageSize);
return users;
}
}
ํ๋กํ ์กฐํ API
async getProfile(userId: number) {
const user = await UserModel.findById(userId, ["P"]);
if (!user) {
throw new NotFoundException("User not found");
}
return {
id: user.id,
username: user.username,
email: user.email,
bio: user.bio,
department: user.employee?.department?.name,
salary: user.employee?.salary,
};
}
๋ณตํฉ ๊ฒ์ API
async searchUsers(params: {
role?: UserRole;
departmentName?: string;
minSalary?: number;
}) {
let query = UserModel.getPuri("r", ["P"]);
if (params.role) {
query = query.where("users.role", params.role);
}
if (params.departmentName) {
query = query.where(
"employee__department.name",
"like",
`%${params.departmentName}%`
);
}
if (params.minSalary) {
query = query.where("employee.salary", ">=", String(params.minSalary));
}
return await query.orderBy("users.username", "asc");
}
Subset ์กฐํฉ
์ฌ๋ฌ Subset ์ฌ์ฉ (Union)
// ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅธ Subset ์ฌ์ฉ
async getUser(userId: number, detailed: boolean) {
if (detailed) {
return await UserModel.findById(userId, ["P"]);
// ํ์
: UserSubsetMapping["P"] | undefined
} else {
return await UserModel.findById(userId, ["SS"]);
// ํ์
: UserSubsetMapping["SS"] | undefined
}
}
์กฐ๊ฑด๋ถ Subset ์ ํ
async getUserData(userId: number, role: UserRole) {
const subsets = role === "admin" ? ["A"] : ["P"];
return await UserModel.findById(userId, subsets);
// ํ์
: UserSubsetMapping["A"] | UserSubsetMapping["P"] | undefined
}
์ฑ๋ฅ ์ต์ ํ
ํ์ํ Subset๋ง ์ฌ์ฉ
// โ ๋์จ: ๋ชฉ๋ก์์ Subset A ์ฌ์ฉ (๊ณผ๋ํ ๋ฐ์ดํฐ)
const users = await UserModel.findMany({
listParams: { page: 1, pageSize: 20 },
subsetKey: "A", // ๋ชจ๋ ํ๋ ๋ก๋ฉ
});
// โ
์ข์: ๋ชฉ๋ก์๋ Subset L ์ฌ์ฉ
const users = await UserModel.findMany({
listParams: { page: 1, pageSize: 20 },
subsetKey: "L", // ํ์ํ ํ๋๋ง
});
JOIN ์ต์ํ
// โ ๋์จ: ๋ถํ์ํ JOIN (Subset P)
const userIds = await UserModel.getPuri("r", ["P"])
.pluck("users.id");
// employee, department ํ
์ด๋ธ๋ JOIN๋จ
// โ
์ข์: JOIN ์๋ Subset (SS)
const userIds = await UserModel.getPuri("r", ["SS"])
.pluck("users.id");
// users ํ
์ด๋ธ๋ง ์กฐํ
Subset๊ณผ Raw Puri ๋น๊ต
Subset ์ฌ์ฉ
// โ
Subset - ํ์
์์ , ๊ฐ๊ฒฐ
const users = await UserModel.getPuri("r", ["P"])
.where("users.role", "admin");
// ํ์
: UserSubsetMapping["P"][]
// JOIN ์๋ ์ค์
// SELECT ์๋ ์ค์
Raw Puri ์ฌ์ฉ
// โ ๏ธ Raw Puri - ์๋ ์ค์
const users = await UserModel.getPuri("r")
.table("users")
.leftJoin("employees", "users.id", "employees.user_id")
.leftJoin("departments", "employees.department_id", "departments.id")
.select({
id: "users.id",
username: "users.username",
employee__salary: "employees.salary",
employee__department__name: "departments.name",
})
.where("users.role", "admin");
// ํ์
: { id: number; username: string; ... }[]
// JOIN ์๋ ์ค์
// SELECT ์๋ ์ค์
// Hydrate ์๋ ์ ์ฉ ํ์
Subset์ ์ฌ์ฉํ์ธ์!
- ํ์
์์ ์ฑ ๋ณด์ฅ
- ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ ํฅ์
- ์ ์ง๋ณด์ ํธ๋ฆฌ
- ์ฟผ๋ฆฌ ์ผ๊ด์ฑ ์ ์ง
๋ค์ ๋จ๊ณ