如何只检索关系 ID,而不是 MikroORM 中的整个实体?
How to retrieve only the relation ID, not the whole entity in MikroORM?
我有以下基本测试实体:
@Entity()
class Author {
@PrimaryKey()
public id!: number;
@Property()
public name!: string;
}
@Entity()
class Book {
@PrimaryKey()
public id!: number;
@Property()
public title!: string;
@ManyToOne({joinColumn: 'authorID'})
public author!: Author;
}
我正在尝试的是 select 只有一个 Book 记录,它的 'author',但我只关心它的 ID,我不想实际加载实体。
如果我简单地调用它,它不会工作(根本没有加载作者数据):
em.getRepository(Book).findOne({id: 1}, {fields: ['id', 'title', 'author.id']});
'author.id' 不起作用,SQL 甚至不包含 'authorID' 字段。
如果我也将 'author' 添加到字段列表中,它会起作用,加载作者(仅使用 ID),但作为一个单独的实体,具有 单独的附加 SQL声明!这就是我要避免的。
em.getRepository(Book).findOne({id: 1}, {fields: ['id', 'title', 'author', 'author.id']})
@1. SQL
select `b0`.`id`, `b0`.`title`, `b0`.`authorID` from `book` as `b0` where `b0`.`id` = 1 limit 1
@2. SQL (this wouldn't be neccessary as I want only the ID)
select `a0`.`id` from `author` as `a0` where `a0`.`id` in (2)
--> Result:
Book: { id: 1, title: 'a book', author: { id: 2 } }
我发现的唯一方法是将特定的 'authorID' 字段也添加到 Book 实体中:
@Property()
public authorID!: number;
但是,我想避免引入这些外键列,最好通过已经存在和使用的 'author' 关系来处理(仅通过 'id' 属性).
是否存在任何解决方案,我可以在不生成第二个 SELECT 语句(对于关系)的情况下检索关系的 ID,甚至避免引入外键(在已经存在的关系旁边 属性)?在没有任何额外 sql 声明的情况下通过关系接收会很棒。
提前致谢。
你看到第二个查询是正确的行为,这就是填充的工作方式,你只想要实体中的一个 属性 这一事实不会改变任何东西,你仍然填充关系,并且每个关系都将使用自己的查询来加载它。如果要使用单个查询,可以使用 LoadStrategy.JOINED
。但这仍然会为该关系做一个连接,这对于您的用例来说是不需要的。
鉴于您只希望 FK 存在,您根本不需要关心目标实体。这也应该可以解决问题:
em.getRepository(Book).findOne(1, {
fields: ['id', 'title', 'author'],
populate: [],
});
这样您就可以说您希望这 3 个属性成为从 Book
实体中选择的内容的一部分。您已经有了 author
属性,它代表 FK。序列化此类实体后,您将得到想要的结果。在运行时,您会在那里看到实体引用 - 一个只有 PK 的实体。当您 console.log 这样的实体时,它表示为 Ref<Author>
。
请注意,您在那里需要 populate: []
,否则会从包含 author
属性 的 fields
中推断出来,这将触发完全加载
我有以下基本测试实体:
@Entity()
class Author {
@PrimaryKey()
public id!: number;
@Property()
public name!: string;
}
@Entity()
class Book {
@PrimaryKey()
public id!: number;
@Property()
public title!: string;
@ManyToOne({joinColumn: 'authorID'})
public author!: Author;
}
我正在尝试的是 select 只有一个 Book 记录,它的 'author',但我只关心它的 ID,我不想实际加载实体。
如果我简单地调用它,它不会工作(根本没有加载作者数据):
em.getRepository(Book).findOne({id: 1}, {fields: ['id', 'title', 'author.id']});
'author.id' 不起作用,SQL 甚至不包含 'authorID' 字段。
如果我也将 'author' 添加到字段列表中,它会起作用,加载作者(仅使用 ID),但作为一个单独的实体,具有 单独的附加 SQL声明!这就是我要避免的。
em.getRepository(Book).findOne({id: 1}, {fields: ['id', 'title', 'author', 'author.id']})
@1. SQL
select `b0`.`id`, `b0`.`title`, `b0`.`authorID` from `book` as `b0` where `b0`.`id` = 1 limit 1
@2. SQL (this wouldn't be neccessary as I want only the ID)
select `a0`.`id` from `author` as `a0` where `a0`.`id` in (2)
--> Result:
Book: { id: 1, title: 'a book', author: { id: 2 } }
我发现的唯一方法是将特定的 'authorID' 字段也添加到 Book 实体中:
@Property()
public authorID!: number;
但是,我想避免引入这些外键列,最好通过已经存在和使用的 'author' 关系来处理(仅通过 'id' 属性).
是否存在任何解决方案,我可以在不生成第二个 SELECT 语句(对于关系)的情况下检索关系的 ID,甚至避免引入外键(在已经存在的关系旁边 属性)?在没有任何额外 sql 声明的情况下通过关系接收会很棒。
提前致谢。
你看到第二个查询是正确的行为,这就是填充的工作方式,你只想要实体中的一个 属性 这一事实不会改变任何东西,你仍然填充关系,并且每个关系都将使用自己的查询来加载它。如果要使用单个查询,可以使用 LoadStrategy.JOINED
。但这仍然会为该关系做一个连接,这对于您的用例来说是不需要的。
鉴于您只希望 FK 存在,您根本不需要关心目标实体。这也应该可以解决问题:
em.getRepository(Book).findOne(1, {
fields: ['id', 'title', 'author'],
populate: [],
});
这样您就可以说您希望这 3 个属性成为从 Book
实体中选择的内容的一部分。您已经有了 author
属性,它代表 FK。序列化此类实体后,您将得到想要的结果。在运行时,您会在那里看到实体引用 - 一个只有 PK 的实体。当您 console.log 这样的实体时,它表示为 Ref<Author>
。
请注意,您在那里需要 populate: []
,否则会从包含 author
属性 的 fields
中推断出来,这将触发完全加载