我一直在使用 Sequelize-Typescript,并且偶然发现了一对多关联。这里我有“相册”和“照片”作为我的实体。一张“相册”有很多“照片”。所以这是我的实体代码供您参考:
专辑.ts
`
@Table({
timestamps: true,
deletedAt: "albumDeletedAt",
paranoid: true,
createdAt: true,
updatedAt: true
})
export class Album extends Model {
@PrimaryKey
@Column({
type: DataType.INTEGER,
primaryKey: true,
autoIncrement: true
})
declare id: number;
@Column({
type: DataType.STRING,
allowNull: false
})
declare name: string;
@Column({
type: DataType.STRING,
allowNull: true
})
declare description?: string;
@Column({
type: DataType.STRING,
allowNull: false
})
declare thumbnailURL: string;
@HasMany(() => Photo)
declare photos: Photo[];
@CreatedAt
declare createdAt: Date;
@UpdatedAt
declare updatedAt: Date;
}`
照片.ts
import { BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, PrimaryKey, Table,
UpdatedAt } from "sequelize-typescript";
import { Album } from "./album";
@Table({
timestamps: true,
deletedAt: "photoDeletedAt",
paranoid: true,
createdAt: true,
updatedAt: true
})
export class Photo extends Model {
@PrimaryKey
@Column({
type: DataType.INTEGER,
primaryKey: true,
autoIncrement: true
})
declare id: number;
@Column({
type: DataType.STRING,
allowNull: false
})
declare name: string;
@Column({
type: DataType.STRING,
allowNull: false
})
declare photoURL: string;
@ForeignKey(() => Album)
@Column({
type: DataType.INTEGER,
allowNull: true,
})
declare albumId: number;
@BelongsTo(() => Album)
declare album: Album;
@CreatedAt
declare createdAt: Date;
@UpdatedAt
declare updatedAt: Date;
}
AlbumRepository.ts
export class AlbumRepository {
private albumRepository: Repository<Album>;
private photoRepository: Repository<Photo>;
/**
* This constructor injects the DatabaseMiddleware class created and annotated as "@Service()"
* @param databaseMiddleware Database Middleware created
*/
constructor(public databaseMiddleware: DatabaseMiddleware) {
this.albumRepository = databaseMiddleware.getDatabaseInstance().getRepository(Album);
this.photoRepository = databaseMiddleware.getDatabaseInstance().getRepository(Photo);
}
/**
* Creates an "Album" data in the database.
* @param albumCreateDTO Album Create DTO data model
* @returns "Album" data entity model (if successfully created in the database) or null.
*/
public async createAlbum(albumCreateDTO: AlbumCreateDto) {
try {
return await this.albumRepository.create({ ...albumCreateDTO }, { include: [this.photoRepository] });
} catch (error) {
console.error("Error while creating an album data to the database due to", error?.message);
return null;
}
}
/**
* Find the album via it's ID
* @param id The ID of the album
* @returns Album (if exists) or null
*/
public async getAlbumById(id: number) : Promise<Album | null> {
try {
return await this.albumRepository.findByPk(id, { include: [this.photoRepository] }) ?? null;
} catch (error) {
console.error(`Error finding the album via ID for the ID of ${id} due to`, error);
return null;
}
}
}
最后,我的 Sequelize-Typescript 实例如下:
export default class DatabaseMiddleware {
private databaseInstance: Sequelize;
constructor() {
this.databaseInstance = new Sequelize({
dialect: "mysql",
host: process.env.DATABASE_HOST,
database: process.env.DATABASE_NAME,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
port: 3306,
// storage: process.env.DATABASE_STORAGE_PATH,
logging(sql, timing) {
console.log("The SQL statement from Sequelize executed is", sql, timing);
},
query: { raw: true }
models: [User, Album, Video, Photo],
repositoryMode: true
});
}
public async connectToDatabase() {
try {
await this.databaseInstance.authenticate();
if (process.env.ENVIRONMENT_PROFILE === "development") {
await this.databaseInstance.sync({ alter: true, force: true });
}
console.log("Connection to database has been established successfully");
} catch (error) {
console.error("Unable to connect to database due to", error);
}
}
public getDatabaseInstance() {
return this.databaseInstance;
}
}
我使用基于类的样式来创建 Express.JS REST API,并且在除实体之外使用的每个类中添加依赖项注入。我可以使用“照片”创建一个“相册”,并且可以在数据库中看到它。但当我调用存储库中的
getAlbumById
函数时,我只得到 1 张“照片”。如果我插入了 3 个“照片”,那么在调用该函数期间,当数据库中有 3 个“照片”时,它仅返回 1 个“照片”。
更新问题描述
以下是在
include: [this.photoRepository]
中使用 AlbumRepository.ts
运行查询后的样子。
如果您有任何解决方案,请在这里分享。谢谢!
从函数
raw: true
中删除 AlbumRepository.ts
标志时出错:由于 TypeError,通过 ID 查找 ID 为 1 的相册时出错:result.get 不是函数 位于 E:\Coding Projects\Projects\Back-Ends\Profilic ode_modules\sequelize\src\model.js:1885:39 在Array.reduce() 位于 E:\Coding Projects\Projects\Back-Ends\Profilic ode_modules\sequelize\src\model.js:1884:19 在Array.map() 在 Function._findSeparate (E:\Coding Projects\Projects\Back-Ends\Profilic ode_modules\sequelize\src\model.js:1881:39) 在 Function.findAll (E:\Coding Projects\Projects\Back-Ends\Profilic ode_modules\sequelize\src\model.js:1840:24) 在 processTicksAndRejections (节点:内部/进程/task_queues:95:5) 在 async Function.findOne (E:\Coding Projects\Projects\Back-Ends\Profilic ode_modules\sequelize\src\model.js:1998:12) 在 async Function.findByPk (E:\Coding Projects\Projects\Back-Ends\Profilic ode_modules\sequelize\src\model.js:1955:12) 在异步AlbumRepository.getAlbumById (E:\Coding Projects\Projects\Back-Ends\Profilic 存储库 lbum.repository.ts:52:20)
解决方案是在交易中添加
getAlbumByID
。例如:
raw: true, nest: true
.
我想要的结果现在如下所示:const searchedResult = await this.albumRepository.findByPk(id, { include: [this.photoRepository], raw: true, nest: true });
}
这是因为sequelize-typescript 使用一个库通过添加子对象和子属性来安全地反序列化子对象。例如:
{
"name": "My Album",
"description": "Personal Album",
"thumbnailURL": "http://localhost:8080/uploads/pictures/my_album/my_album_thumbnail.jpg",
"photos": {
"id": 1,
"name": "3840x2880_2887b808096152458f8e6b41cb5a8780.jpg",
"photoURL": "http://192.168.1.15:8080/uploads/pictures/my_album/3840x2880_2887b808096152458f8e6b41cb5a8780.jpg",
"albumId": 1,
"createdAt": "2024-03-15T11:34:45.000Z",
"updatedAt": "2024-03-15T11:34:45.000Z",
"photoDeletedAt": null
},
"albumDeletedAt": null
标志"photos.id": 1
,将其转换为拥有子对象的常规方式。现在,我提到了这个错误。因为在我的问题描述中,我有一对多的关系,即一个
nest: true
可以有一个或多个Album.ts
。现在,在我的数据库中,即使我有 3 个 Photo.ts
相同的外键 Photo.ts
,它仍然返回我相册中的一张照片。此错误在 GitHub 的拉取请求问题中报告:一对多关系中的错误问题。否则,一切正常。再次感谢那些提供帮助的人。 解决方案的 GitHub 链接:导致此解决方案的讨论