解析多对多模型

Parsing many to many model

我有一个看起来像这样的图书数据库(简化版):

[book]
- bookId
- title
[author]
- authorId
- name
[book_has_author]
- bookId
- authorId

所以基本上一本书可以有多个作者,一个作者可以有多本书。

我创建了一个 express API,它通过内部连接检索了我的作者的书籍列表。一本有 2 位作者的书 returns 是这样的:

[
  {
    bookId: 1,
    title: "how to code",
    authorId: 1,
    name: "martin"
  },
  {
    bookId: 1,
    title: "how to code",
    authorId: 2,
    name: "Tim"
  }
]

但是我的 Angular 模型看起来像这样:

interface Author {
  authorId: number,
  name: string,
  books: Book[]
}
interface Book {
  bookId: number,
  title: string,
  authors: Author[]
}

我知道这是表示我的数据库的一种糟糕方式,但我不知道如何对其建模。

这里的主要问题是接口之间存在循环引用,尽管我想您已经知道了。 这通常是一个问题,虽然从技术上讲以这些术语考虑数据是正确的,但它并不是为数据建模的好方法。

第一个解决方案是在作者 have-books 或书籍 have-authors[=25= 之间做出选择],从而从循环引用中删除依赖项之一。您还可以创建 BookChildAuthorChild 接口,同时保留 BookAuthor 接口,但如果用例真的不值得,那最终会增加不必要的复杂性.

做出选择后,您可能需要在查询结果中添加一些类型安全。为此,您可以创建一个 BookAuthorResponse 接口,然后通过 map 和 reduce 操作或等效命令 (for-loop).

将其转换为 Book
interface Author {
  authorId: number,
  name: string
}

interface Book {
  bookId: number,
  title: string,
  authors: Author[]
}

interface BookAuthorResponse {
  bookId: number
  title: string
  authorId: number
  name: string
}

const bookAuthorResponseArray: BookAuthorResponse[] = [
  {
    bookId: 1,
    title: "how to code",
    authorId: 1,
    name: "martin"
  },
  {
    bookId: 1,
    title: "how to code",
    authorId: 2,
    name: "Tim"
  }
]

const books: Book = bookAuthorResponseArray.map(ba => ({
    bookId: ba.bookId,
    title: ba.title,
    authors: [{
      authorId: ba.authorId,
      name: ba.name
    }]
  }))
  .reduce((ba, acc) => ({
    bookId: ba.bookId,
    title: ba.title,
    authors: [...acc.authors, ba.authors[0]]
  }))