TypeORM:如何实现双向关系,多个字段->一种实体类型

时间:2019-06-25 20:21:35

标签: one-to-many erd typeorm

我创建了一个“文档”实体:

例如

  @OneToOne(type => DocumentEntity)
  @JoinColumn({ name: 'default_document' })
  defaultDocument: DocumentEntity;

  @OneToOne(type => DocumentEntity)
  @JoinColumn({ name: 'featured_document' })
  featuredDocument: DocumentEntity;

  @OneToMany(type => DocumentEntity, document => document.post)
  @JoinColumn({ name: 'other_documents' })
  otherDocs: DocumentEntity[]; 

多个文档可以与不同的实体类型相关:帖子,userProfile等

例如,在post实体中,

我有几个字段都指定了文档关系。

  @ManyToOne(type => abstractEntity, entity => entity.document)
  parentEntity: abstractEntity;

我不清楚如何使文档关系双向。 我希望在文档上有一个单一字段,例如:

documents: [
{
id: 1,
name: 'document 1', 
path: 'https://image.hosted.service/1.jpg', 
parentEntityId: 23
}, 
{
id: 2
name: 'document 2', 
path: 'https://image.hosted.service/2.jpg'
parentEntityId: 27
}
] 

这样,如果我要查询文档实体的父级关系, 我会有类似的结果:

@Entity()
export class Document {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  path: string;
  ...

  @OneToOne(type => PostEntity, post => post.defaultDocument)
  postEntityDefaultDoc: PostEntity;

  @OneToOne(type => PostEntity, post => post.featuredDocument)
  postEntityFeaturedDoc: PostEntity;

  @ManyToOne(type => PostEntity, post => post.otherDocs)
  otherDocs: PostEntity[];


}

但是Typeorm似乎希望我为documentEntity上的每个父关系字段定义一个完全匹配的字段,例如:

        return new RegExp(`(?!<|>|/|&amp|_)(?<!</?[^>]*|&[^;]*)(${term})`, 'gi');
      };
      searchTermsInArray.forEach(term => {
        if (term.length) {
          const regexp = this.regexpFormula(term);
          newQuestion.qtiData.prompt = newQuestion.qtiData.prompt.replace(regexp, match => {
            return `<span class="highlight">${match}</span>`;
          });```

expected:  it will return just the search term with the highlight class and will ignore html tags.  actual results :  works in chrome not firefox

在本示例中,为简单起见,没有M:N关系:文档最多可以有一个父级。

对于父实体字段引用文档的每个可能实例,我都必须在文档实体上定义一个新字段似乎并不正确。 对文档的查询不会返回带有一个定义父实体的字段的列表,而是我必须解析/聚合任意数量的字段。

我似乎找不到任何教程/示例,其中单个实体具有许多字段,每个字段都引用相同的另一个实体,这使我觉得我的基本方法存在缺陷。

1 个答案:

答案 0 :(得分:1)

秘密要素是leftJoinAndMapMany,它使您可以加入任意实体并将其映射到属性上。

这是我要为您处理的情况。 DocumentEntity看起来像这样:

@Entity()
class DocumentEntity {
    @PrimaryGeneratedColumn()
    public id!: number;

    @Column()
    public entity!: string;

    @Column({
        name: 'entity_id',
    })
    public entityId!: string;

    @Column()
    public name!: string;
}

您的PostEntity如下所示:

@Entity()
class PostEntity {
    @PrimaryGeneratedColumn()
    public id!: number;

    @Column()
    public name: string;

    public documents?: DocumentEntity[];
}

您可能会注意到,帖子中的文档没有注释。那是因为我们将使用上述方法进行联接。您的查询看起来像这样:

connection
    .getRepository(PostEntity)
    .createQueryBuilder('p')
    .leftJoinAndMapMany(
        'p.documents',
        DocumentEntity,
        'p__d',
        '(p.id = md.entityId AND md.entity = :documentEntity)',
        {
            documentEntity: PostEntity.name,
        },
    )
    .getMany()

这些方法可用于加入这些实体:

  • leftJoinAndMapMany
  • innerJoinAndMapMany
  • leftJoinAndMapOne
  • innerJoinAndMapOne