【问题标题】:TypeORM: How to order by a relation fieldTypeORM:如何按关系字段排序
【发布时间】:2020-01-12 06:39:50
【问题描述】:

我有一个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;

}

我想得到所有SongsSinger 名称

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

【问题讨论】:

    标签: typescript typeorm


    【解决方案1】:

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

    使用 QueryBuilder 非常简单:

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

    【讨论】:

      【解决方案2】:

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

      为此,您可以将任务委托给像 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);
      

      进一步阅读:

      【讨论】:

      • 如果我能接受 2 个答案,我也会接受你的。这是我使用的方法,但是您以一种非常漂亮和优雅的方式解释了它,谢谢。
      • 谢谢@Budget,不用担心 :) 顺便说一句,其他语言的其他 ORM 实际上支持您的要求。例如,在 C# 中,“实体框架”允许您简单地编写 songs.OrderBy(song => song.singer.name);,它会自动为您执行连接和排序——但不幸的是,TypeORM 不支持这一点:(
      • 你知道 EF Core 是否支持这种类型的功能吗?
      • 我在这里看到 2 个缺点:首先,您添加了另一个依赖项,其次,您在检索数据后进行排序,因此您实际上并未对 DB 数据进行排序,而是对 DB 结果进行排序
      • 嗨@SebastienH。你的观点都是有效的,但我想我已经在第一句话中明确表达了这一点:“如果你愿意通过将任务委托给像lodash这样的库 [...]。
      【解决方案3】:

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

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

      【讨论】:

      • 为什么这有 2 个赞成票,这与问题无关,我们在按关系实体属性排序时遇到问题。
      • @DedaDev 此评论不会改善解决方案,谢谢
      • @SalahED 感谢您在使用存储库时分享解决方案,我在此之后发现您的回答很有用
      • 谢谢!!!!这有效!
      【解决方案4】:

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

      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;
      
      }
      

      【讨论】:

        【解决方案5】:

        如果结果不是太大,您可以使用实体挂钩的解决方法来做到这一点:

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

        【讨论】:

          【解决方案6】:

          我认为 typeorm 增加了对这个特性的支持。在我的代码库中,我使用这样的语法,它根据singer.name 对结果进行排序。

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

          【讨论】:

            【解决方案7】:

            当您使用存储库时:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-11-03
              • 2019-04-12
              • 1970-01-01
              • 2021-02-07
              • 2021-08-28
              • 2019-06-24
              相关资源
              最近更新 更多