【发布时间】:2019-09-05 11:25:03
【问题描述】:
我知道这个问题已经被问过很多次了,但是我他们没有解决数据库 SQL 部分,也没有合适的例子。
目标是使用 REST API 在数据库中插入或更新发票,更具体地说是在发票中插入或更新项目。
数据
数据由两部分组成。
let invoiceHeader = {
id: 123,
key: "2019/00001",
client: 42
}
let invoiceItems = [
{ id: 2001, sku: "A12345", quantity: 10, price: 300 },
{ id: 2002, sku: "B54321", quantity: 6, price: 500 },
{ id: 2003, sku: "C11223", quantity: 20, price: 200 },
]
数据库
此数据需要插入到 2 个数据库表中。
invoice
+-----+------------+--------+
| id | key | client |
+-----+------------+--------+
| 123 | 2019/00001 | 42 |
+-----+------------+--------+
invoiceItems
+------+--------------+--------+----------+-------+
| id | fk_invoiceId | sku | quantity | price |
+------+--------------+--------+----------+-------+
| 2001 | 123 | A12345 | 10 | 300 |
| 2002 | 123 | B54321 | 6 | 500 |
| 2003 | 123 | C11223 | 20 | 200 |
+------+--------------+--------+----------+-------+
发票抬头
发票标题很简单
插入发票标题(创建新发票)
POST http://example.com/api/invoices
{
"key": "2019/00001",
"client": 42
}
INSERT INTO invoice (key, client) VALUES ('2019/00001', 42);
更新发票标头(使用新客户端)
PATCH http://example.com/api/invoices/123
{
"id": 123,
"client": 66
}
UPDATE invoice SET client = 66 WHERE id = 123;
发票项目
但是,发票项目可以通过 2 种方式完成。
方法 1 - 单人
插入发票项目
POST http://example.com/api/invoices/123/items
{ "sku": "A12345", "quantity": 10, "price": 300 }
INSERT INTO invoiceItems (sku, quantity, price) VALUES ('A12345', 10, 300);
POST http://example.com/api/invoices/123/items
{ "sku": "B54321", "quantity": 6, "price": 500 }
INSERT INTO invoiceItems (sku, quantity, price) VALUES ('B54321', 6, 500);
POST http://example.com/api/invoices/123/items
{ "sku": "C11223", "quantity": 20, "price": 200 }
INSERT INTO invoiceItems (sku, quantity, price) VALUES ('C11223', 20, 200);
更新发票项目(新数量和价格)
PATCH http://example.com/api/invoices/123/items/2001
{ "id": 2001, "quantity": 23, "price": 130 }
UPDATE invoiceItems SET quantity = 23, price = 130 WHERE id = 2001;
方法 2 - 批量
插入发票项目
POST http://example.com/api/invoices/123/items
[
{ "sku": "A12345", "quantity": 10, "price": 300 },
{ "sku": "B54321", "quantity": 6, "price": 500 },
{ "sku": "C11223", "quantity": 20, "price": 200 },
]
INSERT INTO invoiceItems (sku, quantity, price)
VALUES
('A12345', 10, 300),
('B54321', 6, 500),
('C11223', 20, 200)
;
更新发票项目(单个项目的新数量和价格)
PATCH http://example.com/api/invoices/123/items
[
{ "id": 2001, "sku": "A12345", "quantity": 23, "price": 130 },
{ "id": 2002, "sku": "B54321", "quantity": 6, "price": 500 },
{ "id": 2003, "sku": "C11223", "quantity": 20, "price": 200 },
]
INSERT INTO table (id, sku, quantity, price)
VALUES
(2001, 'A12345', 10, 300),
(2002, 'B54321', 6, 500),
(2003, 'C11223', 20, 200)
ON DUPLICATE KEY UPDATE
sku = values(sku),
quantity = values(quantity),
price = values(price)
;
总结
单一方法发出大量请求,而批量方法发送不必要的数据。
请记住,一张发票可以轻松包含 300 多件商品。
那么,您认为哪种方法更好?
【问题讨论】:
-
GraphQL 旨在降低 HTTP 请求和灵活数据..
-
@RaymondNijland 我不熟悉 GraphQL。您如何看待这个特定的设置?
-
GraphQL 为多个插入操作提供了一种定义明确的方法。 REST 没有。作为一个(巨大的)奖励,它还可以进行模式验证,并以基本为零的成本提供重要的反射功能。它还可以使用正确的后端处理分页、游标和流数据,与它的接口只需要一个兼容 GraphQL 的客户端,而不是特定于 API 的东西。
-
确实@tadman 现有 GraphQL 框架中的一个问题可能是 N+1 个查询问题。有些在框架中解决(通常称为 Deferreds),有些则需要您自己解决。跨度>
-
@RaymondNijland 由于这是 GraphQL 架构的一个常见问题,因此有一些解决方法,就像您指出的那样。如果你为它定义一个类型,你也可以创建一个 GraphQL “多插入”端点,它只接受一个 X 数组而不是单个 X。