解析多对多模型
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= 之间做出选择],从而从循环引用中删除依赖项之一。您还可以创建 BookChild
和 AuthorChild
接口,同时保留 Book
和 Author
接口,但如果用例真的不值得,那最终会增加不必要的复杂性.
做出选择后,您可能需要在查询结果中添加一些类型安全。为此,您可以创建一个 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]]
}))
我有一个看起来像这样的图书数据库(简化版):
[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= 之间做出选择],从而从循环引用中删除依赖项之一。您还可以创建 BookChild
和 AuthorChild
接口,同时保留 Book
和 Author
接口,但如果用例真的不值得,那最终会增加不必要的复杂性.
做出选择后,您可能需要在查询结果中添加一些类型安全。为此,您可以创建一个 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]]
}))