首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自引用ManyToMany Relationship TypeORM

自引用ManyToMany Relationship TypeORM
EN

Stack Overflow用户
提问于 2017-05-02 21:47:08
回答 4查看 18.8K关注 0票数 15

我刚刚开始使用TypeORM,我正在努力使以下关系发挥作用:

用户->朋友,而朋友也是用户对象.但是,我的getter,getFriends & getFriendsInverse正在工作;我现在想要区分这两者。换句话说,当我执行mysql连接时,我不想在朋友上做左连接,在inverseFriends上做另一个连接。

getter getFriends()需要返回所有朋友,而不管我所在的对象是哪个“侧”。

这有意义吗?

这是我的模型定义:

代码语言:javascript
复制
getFriends() {
    // This method should also return inverseFriends;
    // I do not want to return the concat version; this should
    // happen on the database/orm level
    // So I dont want: this.friends.concat(this.inverseFriends) 
    return this.friends;
}

@ManyToMany(type => User, user => user.friendsInverse, {
    cascadeInsert: false,
    cascadeUpdate: false,
})
@JoinTable()
friends = [];

@ManyToMany(type => User, user => user.friends, {
    cascadeInsert: true,
    cascadeUpdate: true,
    cascadeRemove: false,
})
friendsInverse = [];

我希望有人能理解我的问题:谢谢马特

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-12-27 10:51:31

我相信我迟到了3年,但比以往任何时候都晚。最受欢迎的答案不回答问题,因为它只适用于树状和层次结构,所以如果您遵循这个示例,就会发生这样的情况:

代码语言:javascript
复制
               Fred
               /  \
          Albert  Laura
          /   \
       John   Foo

在本例中,Foo不能与Fred做朋友,因为他只能有一个父级。朋友不是树结构,它就像网。答案如下:

代码语言:javascript
复制
import { Column, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn } from 'typeorm';

@Entity(UserModel.MODEL_NAME)
export class UserModel {
  static MODEL_NAME = 'users';

  @PrimaryGeneratedColumn()
  id?: number;

  @Column({ type: 'varchar', unique: true, length: 50 })
  username: string;

  @Column({ type: 'varchar', length: 50, unique: true })
  email: string;

  @ManyToMany(type => UserModel)
  @JoinTable()
  friends: UserModel[];

  @Column({ type: 'varchar', length: 300 })
  password: string;
}

这将创造一个表格,在那里人与人之间的关系将得到拯救。接下来是重要的事情。如何对此进行查询并获得用户的朋友?这并不像看上去那么容易,我已经花了好几个小时来处理这个问题,而且还不能用TypeORM方法甚至查询生成器来完成它。答案是:原始查询。这将与用户的朋友返回一个数组:

代码语言:javascript
复制
async findFriends(id: Id): Promise<UserModel[]> {
    return await this.userORM.query(
      ` SELECT * 
        FROM users U
        WHERE U.id <> $1
          AND EXISTS(
            SELECT 1
            FROM users_friends_users F
            WHERE (F."usersId_1" = $1 AND F."usersId_2" = U.id )
            OR (F."usersId_2" = $1 AND F."usersId_1" = U.id )
            );  `,
      [id],
    );
  }

(users_friends_users是typeORM为保存用户之间关系的表自动生成的名称)

票数 13
EN

Stack Overflow用户

发布于 2017-06-08 19:43:56

你可以自我引用你的亲戚。下面是一个简单有向图的例子(也就是一个节点可以有一个父图和多个子图)。

代码语言:javascript
复制
@Entity()
export class Service extends BaseEntity {

  @PrimaryGeneratedColumn()
  id: number;
  
  @Column()
  @Index({ unique: true })
  title: string;

  @ManyToOne(type => Service, service => service.children)
  parent: Service;

  @OneToMany(type => Service, service => service.parent)
  children: Service[];
}

要记住的一个重要注意事项是,当使用find*函数从DB读取对象时,这些关系不是自动加载的。

要实际加载它们,您必须立即使用查询生成器并加入它们。(您可以加入多个级别。)举个例子:

代码语言:javascript
复制
let allServices = await this.repository.createQueryBuilder('category')
  .andWhere('category.price IS NULL')
  .innerJoinAndSelect('category.children', 'product')
  .leftJoinAndSelect('product.children', 'addon')
  .getMany();

请注意我如何使用不同的名称来引用它们(categoryproductaddon)。

票数 25
EN

Stack Overflow用户

发布于 2021-11-23 20:39:50

2021在这里搜索相同的问题,并找到一种无需自定义原始SQL的解决方法(为简单性提供了相同的模型):

代码语言:javascript
复制
import { Column, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn, JoinTable } from 'typeorm';

@Entity(UserModel.MODEL_NAME)
export class UserModel {
  static MODEL_NAME = 'users';

  @PrimaryGeneratedColumn()
  id?: number;

  @Column({ type: 'varchar', unique: true, length: 50 })
  username: string;

  @Column({ type: 'varchar', length: 50, unique: true })
  email: string;

  @ManyToMany(type => UserModel)
  @JoinTable({ joinColumn: { name: 'users_id_1' } })
  friends: UserModel[];

  @Column({ type: 'varchar', length: 300 })
  password: string;
}

这里的关键时刻是将joinColumn设置为JoinTable

定义ManyToMany关系时,TypeORM会自动创建n-n表users_friends_users,其中一列名为user_id_1,另一列名为user_id_2 (如果外键相同,则自动递增)。

因此,从该表中选择任意列作为“主联接列”就足够了,而且它可以工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43747765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档