Node.js Postgres:一对多关系的复杂多更新查询

Node.js Postgres:一对多关系的复杂多更新查询,node.js,postgresql,plpgsql,pg,Node.js,Postgresql,Plpgsql,Pg,我的数据库看起来像这样 所以 一个用户可以有多本书 基本的一对多关系 假设一个用户更新了已有的书籍并添加了更多的书籍, 我该如何对此提出质疑 我做了一些研究,得出结论,无论是cte还是功能,都可以拯救我 补丁查询的请求主体(JSON)数据如下所示 { // user data user_id: 1, name : 'Ryan', books : [ { book_id : 1, stock : 500

我的数据库看起来像这样

所以

  • 一个用户可以有多本书
  • 基本的一对多关系
假设一个用户更新了已有的书籍并添加了更多的书籍, 我该如何对此提出质疑

我做了一些研究,得出结论,无论是cte还是功能,都可以拯救我

补丁查询的请求主体(JSON)数据如下所示

{
   // user data
      user_id: 1,
      name : 'Ryan',
      books : [
      {
        book_id : 1,
        stock : 500
      },
      {
        book_id : 2,
        stock : 500
      },
      {
        // this book should be added to the users_books table
        name: 'My new book 1',
        stock : 500
      }

      ]

}

The postgresql update queries for the above data should look like ->


UPDATE users_books(stock) VALUES(500) WHERE user_id = 1 AND book_id 1;
UPDATE users_books(stock) VALUES(500) WHERE user_id = 1 AND book_id 2;
INSERT INTO users_books(user_id,book_id,stock) VALUES(1,3,500);

因此,看看上面的结构,我需要相应地更新books_users表

我目前的理解是将books对象作为jsonb传递给postgresql函数。然后在相应地更新/添加书籍的同时循环浏览它。我不知道如何才能知道用户是否已经有了一本书

你们将如何将这个请求体转换成前面提到的复杂更新查询?
在一个函数中执行这项操作是否完全是事务性的?

您可以在一个语句中完成这项操作,但最好有一些独特的约束,以防止它执行不好的操作。用户图书(图书id、用户id)应该是唯一的,图书(名称)应该是唯一的

这是我的建议

以下是重要的部分:

-- The test data
with data(d) as (VALUES ('
{
      "user_id": 1,
      "name" : "Ryan",
      "books" : [
      {
        "book_id" : 1,
        "stock" : 500
      },
      {
        "book_id" : 2,
        "stock" : 500
      },
      {
        "name": "My new book 1",
        "stock" : 500
      }

      ]

}'::jsonb)
-- Parse the json to get user_id, book_id, stock, and name for each book
), normalized_data as (
    select (d ->> 'user_id')::int as user_id,
       book_id, stock, name
    FROM data
    JOIN LATERAL (SELECT * FROM jsonb_to_recordset(d -> 'books') 
                    as books(book_id int, stock int, name text)
    ) sub ON TRUE
-- Update existing stock
), update_existing as (
  UPDATE users_books set stock = normalized_data.stock
  FROM normalized_data
  WHERE users_books.user_id = normalized_data.user_id
    AND users_books.book_id = normalized_data.book_id
    AND normalized_data.book_id IS NOT NULL
-- insert any new books
), insert_new_book as (
INSERT INTO books (name)
  SELECT name from normalized_data
  WHERE book_id IS NULL
  RETURNING id, name
)
-- insert a record into users_books for new books
INSERT INTO users_books (user_id, book_id, stock)
SELECT user_id, id, stock
FROM insert_new_book
JOIN normalized_data ON normalized_data.name = insert_new_book.name;

所以用户\u books.user\u id和用户\u books.book\u id的组合是唯一的?@madflow yes。但我确实需要维护一对多的关系,我想让这本书是唯一的,并且用户id是唯一的,这会打破一对多的关系,对吧?不,这只会强制每个用户只能有一个条目每本书。不要使book_id和user_id唯一,请使用(book_id,user_id)的组合。让它们都不为空可能是值得的。很好地工作@jeremy为了更好地理解postgresql,你推荐哪本书?