我正在尝试在 TypeORM 上构建一个简单的查询,但我没有使用 INNER JOIN 获取整个数据。我究竟做错了什么?
SQL 查询运行完美,但 typeorm 只返回“watcher”表的数据。
SQL查询
SELECT *
FROM watcher w
INNER JOIN user
ON w.userId = user.id;
Run Code Online (Sandbox Code Playgroud)
类型ORM
async getSystemWideWatchers(): Promise<any[]> {
const query = this.createQueryBuilder('watcher');
const result = await query.innerJoin('user', 'u', 'watcher.userId = u.id').getMany();
console.log(result)
return result;
}
Run Code Online (Sandbox Code Playgroud)
Cem*_*Cem 19
TypeORM 有一个名为 的方法innerJoinAndSelect。你用普通的innerJoin. 这就是为什么不从中选择用户表的原因。
一旦您将该部分更改为innerJoinAndSelect,将从中选择监视表。但是,getMany并getOne返回具有您的实体类型的对象。因此,如果您的实体类型在用户表和观察者表之间没有关系,则所选列将不会包含在返回的对象中。
在向您展示如何添加这些关系之前,我想提一下,您可以选择使用getRawMany函数来获取所有选定的列,但我不建议使用它,因为关系更加整洁(没有原始列名称,您会得到与关系相对应的实体数组),在您的情况下,没有理由不使用关系。
现在,根据我对数据库设计的理解,您有用户,用户有观察者。一个Watcher只能监视一个User,并且可能有多个Watcher监视同一个用户。
在这种情况下,用户与观察者的关系称为“一对多”。
观察者与用户的关系称为“多对一”。
您需要在您的实体中指定此信息。这是一个例子。注意OneToMany装饰器。
@Entity()
export class User {
@PrimaryColumn()
id: number;
@Column()
userName: string;
@OneToMany(type => Watcher, watcher => watcher.user)
watchers: Watcher[];
}
Run Code Online (Sandbox Code Playgroud)
这是相应的观察者实体:
@Entity()
export class Watcher {
@PrimaryColumn()
id: number;
@Column()
watcherName: string;
// we can omit this (and the join condition), if userId is a foreign key
@Column()
userId: number;
@ManyToOne(type => User, user => user.watchers)
user: User;
}
Run Code Online (Sandbox Code Playgroud)
一旦建立了这些关系,您就可以选择一个用户及其所有观察者,反之亦然(选择一个观察者及其观察的用户)。
以下是执行这两项操作的方法:
// Select a user and all their watchers
const query = createQueryBuilder('user', 'u')
.innerJoinAndSelect('u.watchers', 'w'); // 'w.userId = u.id' may be omitted
const result = await query.getMany();
Run Code Online (Sandbox Code Playgroud)
(如果您想包含没有观察者的用户,您可以使用 leftJoin 而不是 innerJoin,您可能知道。)
这可能是您最初尝试做的事情:
// Select a watcher and the user they watch
const query = createQueryBuilder('watcher', 'w')
.innerJoinAndSelect('w.user', 'u'); // 'w.userId = u.id' may be omitted
const result = await query.getMany();
Run Code Online (Sandbox Code Playgroud)
Ade*_*ani 12
以防万一有人遇到另一种情况。添加到 Cem 的回答中。如果数据库中没有定义关系,那么您可以执行以下操作:
const query = createQueryBuilder('user', 'u')
.innerJoinAndMapMany(
'u.ObjectNameToMapDataOn',
EntityName,// or 'tableName'
'IAmAlias',
'u.columnName= IAmAlias.columnName'
)
Run Code Online (Sandbox Code Playgroud)
类似地,可以使用innerJoinAndMapOne。如果您希望有多个带有连接表的记录或单个记录,取决于您的情况。
小智 8
如果两个表之间没有关系,则必须使用getRow().
getOne()并将getMany()返回具有存储库类型的对象,因此删除连接表的数据
这个例子对我有用:
this.userRepository
.createQueryBuilder('user')
.select(['user.username as username', 'o.orderTime as orderTime'])
.where('user.id = :id', {id})
.andWhere('o.callerId = :id', {id})
.innerJoin(OrderEntity, 'o')
.getRawMany()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75848 次 |
| 最近记录: |