【问题标题】:MySQL with Node: how to return nested dataMySQL with Node:如何返回嵌套数据
【发布时间】:2020-05-19 20:57:23
【问题描述】:

我有三个表:post、tag 和 post_tag。

CREATE TABLE post (
  id INT NOT NULL,
  title VARCHAR(45) NULL,
  PRIMARY KEY (id));

CREATE TABLE tag (
  id INT NOT NULL,
  tag VARCHAR(45) NULL,
  PRIMARY KEY (id));

CREATE TABLE post_tag (
  post_id INT NOT NULL,
  tag_id INT NOT NULL,
  PRIMARY KEY (post_id, tag_id),
  INDEX fk_post_tag_tag1_idx (tag_id ASC),
  INDEX fk_post_tag_post_idx (post_id ASC),
  CONSTRAINT fk_post_tag_post
    FOREIGN KEY (post_id)
    REFERENCES post (id),
  CONSTRAINT fk_post_tag_tag1
    FOREIGN KEY (tag_id)
    REFERENCES tag (id));

INSERT INTO post (id, title) VALUES (1, 'post 1');
INSERT INTO post (id, title) VALUES (2, 'post 2');
INSERT INTO tag (id, tag) VALUES (1, 'tag 1');
INSERT INTO tag (id, tag) VALUES (2, 'tag 2');
INSERT INTO post_tag (post_id, tag_id) VALUES (1, 1);
INSERT INTO post_tag (post_id, tag_id) VALUES (1, 2);
INSERT INTO post_tag (post_id, tag_id) VALUES (2, 1);
INSERT INTO post_tag (post_id, tag_id) VALUES (2, 2);

然后我可以创建一个存储过程来检索带有标签的第一篇文章:

DELIMITER $$
CREATE PROCEDURE select_posts_tags(IN id INT)
BEGIN
  SELECT *
  FROM post
    INNER JOIN post_tag pt ON post.id = pt.post_id
    INNER JOIN tag t ON t.id = pt.tag_id
      WHERE post.id = id
      GROUP BY post.id, t.id;
END $$
DELIMITER ;

最后我从 Node 调用存储过程:

var mysql = require("mysql");
var connection = mysql.createConnection({
  host: "127.0.0.1",
  user: "test_database",
  password: "test_database",
  database: "test_database",
});

connection.connect();

const sql = `CALL select_posts_tags(${1})`;

connection.query(sql, (error, results) =>
  console.log(JSON.stringify(results[0], null, 4))
);

connection.end();

但结果是一个平面对象数组:

[
    {
        "id": 1,
        "title": "post 1",
        "post_id": 1,
        "tag_id": 1,
        "tag": "tag 1"
    },
    {
        "id": 2,
        "title": "post 1",
        "post_id": 1,
        "tag_id": 2,
        "tag": "tag 2"
    }
]

结果是一个相同的平面 JSON 对象的数组,用不同的标签重复了两次;

如何将标签作为嵌套数组检索到帖子对象内的 «tags» 键中?结果应该是这样的:

[
  {
    id: 1,
    title: "post 1",
    tags: [
      {
        id: 1,
        tag: "tag 1",
      },
      {
        id: 2,
        tag: "tag 2",
      },
    ],
  },
];

谢谢!

【问题讨论】:

    标签: mysql sql json stored-procedures


    【解决方案1】:

    您可以使用json_arrayagg()json_object(),如下所示:

    SELECT 
        p.id, 
        p.title,
        json_arrayagg(json_object('id', t.id, 'tag', t.tag)) tags
    FROM post p
    INNER JOIN post_tag pt ON p.id = pt.post_id
    INNER JOIN tag t ON t.id = pt.tag_id
    WHERE p.id = ?
    GROUP BY p.id, p.title;
    

    【讨论】:

    • 谢谢,有道理……但我在标签数组中转义了 JSON:"[{\"id\": 1, \"tag\": \"tag 1\"}, {\"id\": 2, \"tag\": \"tag 2\"}]"。有没有办法避免这种情况?
    • 以字符串形式返回的嵌套 JSON 的错误是由于使用了 npm mysql 包而不是 mysql2
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    相关资源
    最近更新 更多