不使用 QueryBuilder 的 TypeOrm 连接
TypeOrm Joins without using QueryBuilder
我有3张桌子
- 出席人数
- 用户
- attendance_verification.
出勤->ManyToOne->用户
考勤->OneToOne->考勤验证
现在我想查询特定用户的出勤情况,并希望在出勤对象和 return 中嵌入完整的用户和出勤验证数据。
这是我尝试过的方法,但它给了我错误 Invalid syntax near where.
我试过了
const listOfAttendance = await this.attendanceRepository.find({
where: {
punchInDateTime: Between(dateFrom, dateTo),
},
order: {
id: 'ASC',
},
join: {
alias: 'attendance',
leftJoinAndSelect: {
user: 'attendance.user',
outlet: 'attendance.outlet',
punchAck: 'attendance.punchAck',
verification: 'attendance.attendanceVerification',
},
},
})
TypeORM 正在解析查询
SELECT
"attendance"."id" AS "attendance_id",
"attendance"."punchInImage" AS "attendance_punchInImage",
"attendance"."punchInDateTime" AS "attendance_punchInDateTime",
"attendance"."punchInComment" AS "attendance_punchInComment",
"attendance"."punchOutDateTime" AS "attendance_punchOutDateTime",
"attendance"."punchOutComment" AS "attendance_punchOutComment",
"attendance"."punchOutImage" AS "attendance_punchOutImage",
"attendance"."status" AS "attendance_status",
"attendance"."approvalStatus" AS "attendance_approvalStatus",
"attendance"."userId" AS "attendance_userId",
"attendance"."outletId" AS "attendance_outletId",
"attendance"."createdAt" AS "attendance_createdAt",
"user"."id" AS "user_id",
"user"."firstName" AS "user_firstName",
"user"."lastName" AS "user_lastName",
"user"."userName" AS "user_userName",
"user"."contact" AS "user_contact",
"user"."gender" AS "user_gender",
"user"."dob" AS "user_dob",
"user"."country" AS "user_country",
"user"."state" AS "user_state",
"user"."postalCode" AS "user_postalCode",
"user"."isAdmin" AS "user_isAdmin",
"user"."isEmployee" AS "user_isEmployee",
"user"."byEmail" AS "user_byEmail",
"user"."byContact" AS "user_byContact",
"user"."address" AS "user_address",
"user"."email" AS "user_email",
"user"."orgId" AS "user_orgId",
"user"."password" AS "user_password",
"user"."salt" AS "user_salt",
"user"."createdBy" AS "user_createdBy",
"user"."status" AS "user_status",
"user"."apiAccessKey" AS "user_apiAccessKey",
"user"."createdAt" AS "user_createdAt",
"user"."metaId" AS "user_metaId",
"outlet"."id" AS "outlet_id",
"outlet"."name" AS "outlet_name",
"outlet"."comment" AS "outlet_comment",
"outlet"."location" AS "outlet_location",
"outlet"."status" AS "outlet_status",
"outlet"."orgId" AS "outlet_orgId",
"outlet"."validated" AS "outlet_validated",
"punchAck"."id" AS "punchAck_id",
"punchAck"."isPunchedIn" AS "punchAck_isPunchedIn",
"punchAck"."isAck" AS "punchAck_isAck",
"punchAck"."userId" AS "punchAck_userId",
"punchAck"."dateTime" AS "punchAck_dateTime",
"punchAck"."rejectComment" AS "punchAck_rejectComment",
"punchAck"."attendanceId" AS "punchAck_attendanceId",
"verification"."id" AS "verification_id",
"verification"."status" AS "verification_status",
"verification"."punchIn" AS "verification_punchIn",
"verification"."punchOut" AS "verification_punchOut",
"verification"."supervisorId" AS "verification_supervisorId",
"verification"."attendanceId" AS "verification_attendanceId",
"verification"."comment" AS "verification_comment",
"verification"."createdAt" AS "verification_createdAt"
FROM
"tenant"."attendance" "attendance"
LEFT JOIN "tenant"."users" "user" ON "user"."id" = "attendance"."userId"
LEFT JOIN "tenant"."outlet" "outlet" ON "outlet"."id" = "attendance"."outletId"
LEFT JOIN "tenant"."punch_ack" "punchAck" ON "punchAck"."attendanceId" = "attendance"."id"
LEFT JOIN "tenant"."attendance_verification" "verification" ON
WHERE
"attendance"."punchInDateTime" BETWEEN $ 1
AND $ 2
ORDER BY
"attendance"."id" ASC
PARAMETERS:[
"2021-02-28T19:00:00.000Z",
"2021-03-31T18:59:59.000Z"
]
AttendanceEntity(排除了一些字段以使代码干净)
import { ApiPropertyOptional } from '@nestjs/swagger'
import {
BaseEntity,
Column,
Entity,
ManyToOne,
OneToMany,
OneToOne,
PrimaryGeneratedColumn,
} from 'typeorm'
import { AttendanceVerification } from '@modules/attendance/attendance-verification/attendance_verification.entity'
import { Break } from '@modules/attendance/break/break.entity'
import { PunchAck } from '@modules/attendance/punch-ack/punch_ack.entity'
import { Outlet } from '@modules/outlet/outlet.entity'
import { User } from '@modules/users/users.entity'
@Entity('attendance')
export class Attendance extends BaseEntity {
@ApiPropertyOptional()
@PrimaryGeneratedColumn()
id: number
@ApiPropertyOptional()
@Column()
punchInImage: string
@ApiPropertyOptional()
@Column({ type: 'timestamp' })
punchInDateTime: Date
@ApiPropertyOptional()
@Column()
approvalStatus: string
@ApiPropertyOptional()
@Column()
userId: number
@ApiPropertyOptional()
@Column()
outletId: number
@ManyToOne(type => User, user => user.attendance)
user: User
@OneToOne(type => Outlet, outlet => outlet.attendance)
outlet: Outlet
@OneToMany(type => Break, breaks => breaks.attendance)
breaks: Break[]
@OneToMany(type => PunchAck, punchAck => punchAck.attendance)
punchAck: PunchAck[]
@OneToOne(
type => AttendanceVerification,
attendanceVerification => attendanceVerification.attendance
)
attendanceVerification: AttendanceVerification
}
我在互联网上找到的所有解决方案都使用 queryBuilder。我不想用那种冗长的方法。
来自 typeorm 文档:https://typeorm.io/#/find-options
您可以使用类似的东西:
userRepository.find({
join: {
alias: "user",
leftJoinAndSelect: {
profile: "user.profile",
photo: "user.photos",
video: "user.videos"
}
}
});
或者您的示例可能如下所示:
const returnedResult = await this.attendanceRepository.findOne({
where: { userId: id, status: 'PUNCHED IN' },
join: {
alias: "attendance",
leftJoinAndSelect: {
user: "attendance.user",
outlet: "attendance.outlet",
}
},
});
根据我的个人经验,如果您需要编写复杂的查询,则必须使用 QueryBuilder。乍一看很别扭
我有3张桌子
- 出席人数
- 用户
- attendance_verification.
出勤->ManyToOne->用户
考勤->OneToOne->考勤验证
现在我想查询特定用户的出勤情况,并希望在出勤对象和 return 中嵌入完整的用户和出勤验证数据。 这是我尝试过的方法,但它给了我错误 Invalid syntax near where.
我试过了
const listOfAttendance = await this.attendanceRepository.find({
where: {
punchInDateTime: Between(dateFrom, dateTo),
},
order: {
id: 'ASC',
},
join: {
alias: 'attendance',
leftJoinAndSelect: {
user: 'attendance.user',
outlet: 'attendance.outlet',
punchAck: 'attendance.punchAck',
verification: 'attendance.attendanceVerification',
},
},
})
TypeORM 正在解析查询
SELECT
"attendance"."id" AS "attendance_id",
"attendance"."punchInImage" AS "attendance_punchInImage",
"attendance"."punchInDateTime" AS "attendance_punchInDateTime",
"attendance"."punchInComment" AS "attendance_punchInComment",
"attendance"."punchOutDateTime" AS "attendance_punchOutDateTime",
"attendance"."punchOutComment" AS "attendance_punchOutComment",
"attendance"."punchOutImage" AS "attendance_punchOutImage",
"attendance"."status" AS "attendance_status",
"attendance"."approvalStatus" AS "attendance_approvalStatus",
"attendance"."userId" AS "attendance_userId",
"attendance"."outletId" AS "attendance_outletId",
"attendance"."createdAt" AS "attendance_createdAt",
"user"."id" AS "user_id",
"user"."firstName" AS "user_firstName",
"user"."lastName" AS "user_lastName",
"user"."userName" AS "user_userName",
"user"."contact" AS "user_contact",
"user"."gender" AS "user_gender",
"user"."dob" AS "user_dob",
"user"."country" AS "user_country",
"user"."state" AS "user_state",
"user"."postalCode" AS "user_postalCode",
"user"."isAdmin" AS "user_isAdmin",
"user"."isEmployee" AS "user_isEmployee",
"user"."byEmail" AS "user_byEmail",
"user"."byContact" AS "user_byContact",
"user"."address" AS "user_address",
"user"."email" AS "user_email",
"user"."orgId" AS "user_orgId",
"user"."password" AS "user_password",
"user"."salt" AS "user_salt",
"user"."createdBy" AS "user_createdBy",
"user"."status" AS "user_status",
"user"."apiAccessKey" AS "user_apiAccessKey",
"user"."createdAt" AS "user_createdAt",
"user"."metaId" AS "user_metaId",
"outlet"."id" AS "outlet_id",
"outlet"."name" AS "outlet_name",
"outlet"."comment" AS "outlet_comment",
"outlet"."location" AS "outlet_location",
"outlet"."status" AS "outlet_status",
"outlet"."orgId" AS "outlet_orgId",
"outlet"."validated" AS "outlet_validated",
"punchAck"."id" AS "punchAck_id",
"punchAck"."isPunchedIn" AS "punchAck_isPunchedIn",
"punchAck"."isAck" AS "punchAck_isAck",
"punchAck"."userId" AS "punchAck_userId",
"punchAck"."dateTime" AS "punchAck_dateTime",
"punchAck"."rejectComment" AS "punchAck_rejectComment",
"punchAck"."attendanceId" AS "punchAck_attendanceId",
"verification"."id" AS "verification_id",
"verification"."status" AS "verification_status",
"verification"."punchIn" AS "verification_punchIn",
"verification"."punchOut" AS "verification_punchOut",
"verification"."supervisorId" AS "verification_supervisorId",
"verification"."attendanceId" AS "verification_attendanceId",
"verification"."comment" AS "verification_comment",
"verification"."createdAt" AS "verification_createdAt"
FROM
"tenant"."attendance" "attendance"
LEFT JOIN "tenant"."users" "user" ON "user"."id" = "attendance"."userId"
LEFT JOIN "tenant"."outlet" "outlet" ON "outlet"."id" = "attendance"."outletId"
LEFT JOIN "tenant"."punch_ack" "punchAck" ON "punchAck"."attendanceId" = "attendance"."id"
LEFT JOIN "tenant"."attendance_verification" "verification" ON
WHERE
"attendance"."punchInDateTime" BETWEEN $ 1
AND $ 2
ORDER BY
"attendance"."id" ASC
PARAMETERS:[
"2021-02-28T19:00:00.000Z",
"2021-03-31T18:59:59.000Z"
]
AttendanceEntity(排除了一些字段以使代码干净)
import { ApiPropertyOptional } from '@nestjs/swagger'
import {
BaseEntity,
Column,
Entity,
ManyToOne,
OneToMany,
OneToOne,
PrimaryGeneratedColumn,
} from 'typeorm'
import { AttendanceVerification } from '@modules/attendance/attendance-verification/attendance_verification.entity'
import { Break } from '@modules/attendance/break/break.entity'
import { PunchAck } from '@modules/attendance/punch-ack/punch_ack.entity'
import { Outlet } from '@modules/outlet/outlet.entity'
import { User } from '@modules/users/users.entity'
@Entity('attendance')
export class Attendance extends BaseEntity {
@ApiPropertyOptional()
@PrimaryGeneratedColumn()
id: number
@ApiPropertyOptional()
@Column()
punchInImage: string
@ApiPropertyOptional()
@Column({ type: 'timestamp' })
punchInDateTime: Date
@ApiPropertyOptional()
@Column()
approvalStatus: string
@ApiPropertyOptional()
@Column()
userId: number
@ApiPropertyOptional()
@Column()
outletId: number
@ManyToOne(type => User, user => user.attendance)
user: User
@OneToOne(type => Outlet, outlet => outlet.attendance)
outlet: Outlet
@OneToMany(type => Break, breaks => breaks.attendance)
breaks: Break[]
@OneToMany(type => PunchAck, punchAck => punchAck.attendance)
punchAck: PunchAck[]
@OneToOne(
type => AttendanceVerification,
attendanceVerification => attendanceVerification.attendance
)
attendanceVerification: AttendanceVerification
}
我在互联网上找到的所有解决方案都使用 queryBuilder。我不想用那种冗长的方法。
来自 typeorm 文档:https://typeorm.io/#/find-options 您可以使用类似的东西:
userRepository.find({
join: {
alias: "user",
leftJoinAndSelect: {
profile: "user.profile",
photo: "user.photos",
video: "user.videos"
}
}
});
或者您的示例可能如下所示:
const returnedResult = await this.attendanceRepository.findOne({
where: { userId: id, status: 'PUNCHED IN' },
join: {
alias: "attendance",
leftJoinAndSelect: {
user: "attendance.user",
outlet: "attendance.outlet",
}
},
});
根据我的个人经验,如果您需要编写复杂的查询,则必须使用 QueryBuilder。乍一看很别扭