TypeORM:将不相关的实体映射到数组属性中

Dmi*_*kov 5 typeorm nestjs

我有以下不相关的TypeORM 实体(由于各种原因,我无法在它们上使用一对多关系):

@Entity()
export class Book {
   @PrimaryGeneratedColumn()
   id: number;

   @Column()
   name: string;
}

@Entity()
export class BookCategory {
   @PrimaryGeneratedColumn()
   id: number;

   @Column()
   bookId: number;

   @Column()
   name: string;
}
Run Code Online (Sandbox Code Playgroud)

对于一本书,两个指定的类别和以下查询:

const query = this.bookRepository
      .createQueryBuilder('book')
      .leftJoinAndSelect(BookCategory, 'category', 'book.id = category.bookId');

return query.execute();
Run Code Online (Sandbox Code Playgroud)

我得到以下回复:

[
  {
    "book_id": 1,
    "book_name": "Lorem Ipsum",
    "category_id": 1,
    "category_name": "non-fiction"
  },
  {
    "book_id": 1,
    "book_name": "Lorem Ipsum",
    "category_id": 2,
    "category_name": "documentary"
  }
]
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我得到了 2 个对象。有什么方法可以通过 TypeORM 查询获取以下内容吗?

[
  {
    "id": 1,
    "name": "Lorem Ipsum",
    "categories": ["non-fiction", "documentary"]
  }
]
Run Code Online (Sandbox Code Playgroud)

即我试图将查询结果绑定到虚拟属性categories。那可能吗?

Vic*_*mas 1

我认为 TypeORM 本身不可能做到这一点,但您可以map()通过以下方式使用函数来实现它:

const categories: string[] = query.execute().map((book) => book.category_name );
const book = {id: bookArray[0].book_id, name: bookArray[0].book_name, categories};

//OUTPUT: 
{
  id: 1,
  name: 'Lorem Ipsum',
  categories: [ 'non-fiction', 'documentary' ]
}
Run Code Online (Sandbox Code Playgroud)

这不是最干净的方法,但由于您通过 ID 请求一本书,因此您将确保每个数组对象中的book_idbook_name属性始终相同。

TypeORM 还建议使用getMany()orgetOne()代替执行查询:

const books: Book[] = await this.bookRepository
  .createQueryBuilder('book')
  .leftJoinAndSelect(BookCategory, 'category', 'book.id = category.bookId')
  .getMany();
Run Code Online (Sandbox Code Playgroud)