具有别名的计算列未映射到 TypeORM 实体

Zun*_*iar 5 mysql calculated-columns typescript typeorm

我正在尝试在Express.js项目中使用TypeORM从MySQL数据库的表中获取数据。

我用来QueryBuilder获取数据。

我的实现:

const result = await this.repository.createQueryBuilder("post")
                     .skip((request.PageNo - 1) * request.PageSize)
                     .take(request.PageSize)
                     .select([
                        "post.Id",
                        "post.Title",
                        "SUBSTRING(post.Content, 1, 150) AS post_Content",
                        "post.ReadTime",
                        "post.CreatedDate"
                     ])
                    .getRawAndEntities();
Run Code Online (Sandbox Code Playgroud)

结果:

{
  raw: [
    TextRow {
      post_Id: '457457',
      post_CreatedDate: 2021-03-17T18:00:00.000Z,
      post_Title: 'This is a random title',
      post_ReadTime: 3,
      post_Content: "If you're looking for random paragraphs, you've come to the right place. When a random word or a random sentence isn't quite enough, the next logical "
    }
  ],
  entities: [
    Post {
      CreatedBy: '',
      CreatedDate: 2021-03-17T18:00:00.000Z,
      Content: '',
      Title: 'This is a random title',
      ReadTime: 3,
      IsFeatured: false,
      Id: '457457'
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

期望: 如您所见,我需要该Content列的子字符串。我想我已经添加了别名作为 TypeORM 约定。但该列未映射到该属性。

我还获得了原始数据,您可以在其中看到具有别名的列的子字符串正在工作。

我尝试过的替代方案:

  • "SUBSTRING(post.Content, 1, 150)"
  • "SUBSTRING(post.Content, 1, 150) AS Content"
  • "SUBSTRING(post.Content, 1, 150) AS post.Content"
  • “SUBSTRING(post.Content, 1, 150) AS `post.Content`”

但没有一个将Content列映射到实体Content的属性Post

注意:Content仅当我不使用任何别名时才会映射该列。

对于跟踪: 生成的原始 SQL:

  1. 不使用别名时

    SELECT `post`.`Id` AS `post_Id`, `post`.`CreatedDate` AS `post_CreatedDate`, `post`.`标题` AS `post_Title`, `post`.`Content` AS `post_Content`, ` post`.`ReadTime` AS `post_ReadTime` FROM `Posts` `post` LIMIT 10

  2. 使用别名时

    SELECT `post`.`Id` AS `post_Id`, `post`.`CreatedDate` AS `post_CreatedDate`, `post`.`Title` AS `post_Title`, `post`.`ReadTime` AS `post_ReadTime`, SUBSTRING (`post`.`Content`, 1, 150) AS `post_Content` FROM `Posts` `post` LIMIT 10

请帮忙!!!

编辑(工作解决方案):

const result = await this.repository.createQueryBuilder("post")
                     .skip((request.PageNo - 1) * request.PageSize)
                     .take(request.PageSize)
                     .select([
                        "post.Id",
                        "post.Title",
                        "post.Content",
                        "SUBSTRING(post.Content, 1, 150) AS post_Content",
                        "post.ReadTime",
                        "post.CreatedDate"
                     ])
                    .getMany();
Run Code Online (Sandbox Code Playgroud)

Edw*_*ard 9

多年来,很多人都问过同样的问题。

例子:

  • 问题 296选择其他计算列(仍处于打开状态)
  • 问题 1822添加自定义选择并映射到实体的属性(因重复而关闭)
  • 问题 7008无法使用计算结果添加选择(仍处于打开状态)
  • PR 4703添加了对选择计算列的支持(仍然开放)
  • PR 6855向 MySQL 驱动程序添加选择和映射功能(仍然开放)

typeorm 作者于 2018-03-26 在 Issue 1822 上发表的评论:“名为 addSelectAndMap 的官方解决方案将在 0.3.0 中进入 QueryBuilder”(目前还没有迹象)。

关于问题 #1822,有一个带有解决方法的评论。

首先,您必须添加{ select: false }到实体中的计算列

@Column({ select: false } )
Content: string;
Run Code Online (Sandbox Code Playgroud)

然后用于addSelect(selection, alias)计算列(带有别名重载的 addSelect)

addSelect("SUBSTRING(post.Content,1,3)", "post_Content")
Run Code Online (Sandbox Code Playgroud)