TypeORM:如何按关系字段排序

TypeORM: How to order by a relation field

我有一个 Singer 实体和一个相关的 Song 实体

Singer实体

export class Singer {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @OneToMany( type => Song, Song => Song.user )
    songs: Song[];

}

Song实体

export class Song {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @ManyToOne( type => Singer, Singer => Singer.songs )
    singer: Singer;

}

我想按 Singer 姓名

订购所有 Songs

我搜索了文档和 GitHub 问题,但找不到答案 我该如何解决这个问题?没有 QueryBuilder

会更好

我认为没有查询生成器的 typeorm 目前不支持它,目前有一个 feature request 打开

虽然使用 QueryBuilder 非常简单:

connection.createQueryBuilder(Song, 'songs')
   .leftJoinAndSelect('songs.singer', 'singer')
   .orderBy('singer.name', 'ASC')
   .getMany();

如果您愿意在内存中进行排序,则不必使用查询生成器。 (注意:这意味着先获取所有数据集,然后在您的节点服务器上进行过滤)。

为此,您可以将任务委托给像 lodash 这样的库。这样,您仍然可以使用 EntityManagerRepository 来查询数据。

// first fetch the song and include (=join) the
// singer by the foreign key "singer"
var queryResult = await this.entityManager.find(Song, {
  relations: ['singer'],
});

// then use a library like lodash to do the ordering
const songsSortedBySinger = _.orderBy(queryResult, song => song.singer.name);

进一步阅读:

当您使用存储库时:

var queryResult = await this.youRepository.find(Song, {
  relations: ['singer'],
  order: {
        name: 'ASC',
      },
});

如果结果不是太大,您可以使用实体挂钩的变通方法来实现:

  @AfterLoad()
  sortItems() {
    if (this?.sortableItems?.length) {
      this.sortableItems.sort((a, b) => a.weight - b.weight);
    }
  }

我遇到了同样的问题,我尝试按自定义列排序但没有查询生成器,因为我使用的是存储库,这是我的解决方案:

let res = await this.trackingRepository.findAndCount({
      where: [{ username : Like(`%${searchValue}%`) },
              { action : Like(`%${searchValue}%`) },
              { ip : Like(`%${searchValue}%`) }],
      order: {
        [sortField]: sortOrder === "descend" ? 'DESC' : 'ASC',
      },
      skip: (current - 1) * pageSize,
      take: pageSize,
    });

我认为 typeorm 添加了对此功能的支持。在我的代码库中,我使用了这样的语法,它根据 singer.name.

对结果进行排序
const queryResult = await this.songRepository.find(Song, {
  relations: ['singer'],
  order: {
        'singer.name': 'ASC',
      },
});

在实体模型上尝试默认顺序

https://github.com/typeorm/typeorm/blob/master/sample/sample30-default-order-by/entity/Post.ts

@Entity("sample30_post", {
    orderBy: {
        title: "ASC",
        id: "DESC"
    }
})
export class Post {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    title: string;

}

TypeORM 0.3.0 开始支持:

songRepository.find({
    order: {
        singer: {
            name: "ASC"
        }
    }
})