【问题标题】:Typeorm many-to-many with pivot in javascriptTypeorm 多对多与 javascript 中的枢轴
【发布时间】:2020-06-14 14:42:41
【问题描述】:

我使用 Laravel 作为主后端应用程序,我想连接到该应用程序的数据库。我为 Node.js 选择了 Typeorm,在其中使用 Javascript 和 babel 编译器。

我正在尝试通过数据透视表在用户和挑战实体之间创建多对多关系。

用户:

import { EntitySchema } from 'typeorm'
import User from '../models/User'

export default new EntitySchema({
  name: 'User',
  target: User,
  tableName: 'users',
  columns: {
    id: {
      primary: true,
      type: 'int',
      generated: true
    },
    email: {
      type: 'varchar',
      nullable: false,
      unique: true
    },
    name: {
      type: 'varchar',
      nullable: false
    }
  }
}, {
  relations: {
    challenges: {
      name: 'challenges',
      target: 'Challenge',
      type: 'many-to-many',
      joinTable: {
        name: 'users_challenges',
        joinColumn: {
          name: 'user_id'
        }
      },
      cascade: true
    }
  }
})

挑战:

import { EntitySchema } from 'typeorm'
import Challenge from '../models/Challenge'

export default new EntitySchema({
  target: Challenge,
  name: 'Challenge',
  tableName: 'challenges',
  columns: {
    id: {
      primary: true,
      type: 'int',
      generated: true
    },
    title: {
      type: 'varchar',
      nullable: false
    },
    description: {
      type: 'text',
      nullable: false
    }
  }
}, {
  relations: {
    users: {
      target: 'User',
      type: 'many-to-many',
      joinTable: {
        name: 'users_challenges',
        joinColumn: {
          name: 'challenge_id'
        }
      }
    }
  }
})

数据透视表有以下列:

id
user_id
challenge_id

通过以上所有这些,我正在尝试从 users 表中查询数据:

const userRepository = (await db()).getRepository(User)
const profile = await userRepository
  .findOne({ id: req.body.userId }, {
    relations: ['challenges']
  })

console.log(profile)

我得到这个错误:

Error: Relation "challenges" was not found, please check if it is correct and really exist in your entity.

我如何让它工作?

【问题讨论】:

  • 您查看过文档中 typeorm 提供的示例吗?这里github.com/typeorm/typeorm/blob/master/docs/… 这行在文档中也很重要,JoinTable() 是ManyToMany 关系所必需的。您必须将 JoinTable 放在关系的一侧(拥有)。
  • 我在 User 和 Challenge 实体中都有 joinTable 对象,我无法将布尔值传递给 joinTable,因为我需要指定数据透视表,它已经存在于数据库中。
  • 我唯一的建议是让您的关系正常工作,首先要完全按照文档所说的而不是尝试自定义。如果这不起作用,则创建最小的复制并将其推送到 github 上,以便其他人可以提供更多帮助。
  • 虽然文档声明该关系必须由一方拥有,并且它确实引导您了解它是如何使用装饰器完成的,但没有关于使用 EntitySchemas 时等效的文档。也许我遗漏了一些东西,但是在不使用装饰器的情况下从关系的非所有者端进行查询时,我遇到了多对多关系的类似问题。

标签: javascript node.js typeorm


【解决方案1】:

我和我的一个朋友一起调试了这个,并通过源代码和示例代码找出了使用EntitySchema 的“双向”关系的正确方法。

根据docs,关系必须归一方所有,并且只有一方拥有,无论它是否是双向关系(这意味着您将从任一方访问该关系)。当关系由一方“拥有”时,如上面 cmets 中提到的itwolfpower。这只是意味着每个关系可能只有一个 joinTable 配置。

在您的示例中:假设User 拥有该关系。这相当于将整个 joinTable 配置对象放在 User EntitySchema 对象上:

...
  relations: {
    challenges: {
      name: 'challenges',
      target: 'Challenge',
      type: 'many-to-many',
      joinTable: {
        name: 'users_challenges',
        joinColumn: {
          name: 'user_id'
        },
        inverseJoinColumn: {
          name: 'challenge_id'
        },
      },
      inverseSide: 'User', <--- This needs to match the `target` of the users relation in the Challenge EntitySchema
      cascade: true
    }
  }
...

TLDR;将 inverseJoinColumn 键添加到 joinTable 配置,并将 inverseSide 添加到 challenges 对象。

为了从您的Challenge EntitySchema 访问users 关系,您至少需要将配置设置为以下内容:

...
  relations: {
    users: {
      type: 'many-to-many',
      inverseSide: 'challenges',
      target: 'User' <--- This needs to match the `inverseSide` of the challenges relation in the User EntitySchema
    }
  }
...

这允许您从关系的双方运行查询:

从用户方面:

const userChallenges = await userRepository.findOne(1, { relations: ['challenges'] }

从挑战方面:

const challengeUsers = await challengeRepository.findOne(1, { relations: ['users'] }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-20
    • 2018-11-27
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 2014-01-08
    • 2021-07-16
    • 2019-11-17
    相关资源
    最近更新 更多