node的mysql一个问题,关于数据绑定问题
发布于 6天前 作者 hinson0 261 次浏览 来自 问答

表 post id content user_id

表 comment id content post_id

前端工程师想要的数据格式:

[
  {
    "id": "帖子id,整型",
    "content": "帖子内容,字符串",
    "comments": [
      {
        "id": "评论ID,整型",
        "content": "评论内容,整型",
        "post_id": "所属帖子ID,整型",
      },
      ...
    ]
  }
]

node的代码我是这么写的:假设去用户ID=1的帖子

// 上面省略代码...
function Post() {
  
}

// 获取帖子
Post.getListByUserId = function(userId, callback) {
    var query = db.query('SELECT * FROM post WHERE user_id = ?',  userId,  function(err, posts) {
      // 出错
      if (err) {
        console.log(err);
        return;
      }
      
      // 遍历帖子  -> 下面的代码是有问题的代码,第一次用Node,按照PHP那种同步的思想来做了,不知道怎么得到前端工程师想要的这样的数据结构????
      // 问题1:db.query 是异步的,所以我不知道如何收集结果集
      posts.forEach(function(post) {
        db.query('SELECT * FROM comment WHERE post_id = ?', post.id, function(err, comments) {
          post.comments = comments;
        });
      });
      
      return callback(posts);
  });
}
14 回复

使用left join即可

@i5ting left join的数据结构是平行的。


db.query('SELECT post.*, comment.content AS comment_content, comment.id AS comment_id FROM post INNER JOIN comment ON post.id = comment.post_id WHERE user_id = ?', ...);

你有没有打印出来看一看啊。你这么写没什么问题。唯一我觉得有点毛病的是db.query是异步的,post.comments = comments;还没执行就已经return callback(posts);了。。你先打印一下看看你的结果。如果posts部分是空,function(err, comments,callback(posts){ })这样子嵌套一下去做。

对了,callback最好一层层往下传,尽量不要闭包用。。。

用sql关联 left join 然后将结果稍微改成前端需要的格式即可

异步的函数返回的数据需要聚合,去看看 eventproxy 这个库

你这种数据格式本来用mongo最合适,不过mysql也可以办到,就是写两个查询,msyql属性可以设置multipleStatements: true, 代表可以执行两个查询语句,之所以这样是因为left join也无法得到这种带数组的数据结构,至少我还不知道,所以你可以拿到查询的结果rows[0],rows[1],然后拼接为这种数据结构

async欢迎你

Promise.All 貌似可以

在查询callback中递归调用

db.query(query, function(err, rows) {
  if(!err) {
    index++;
    //递归调用
  }
});

简单到一了,这种查询不要请求太多,任何一次额外的请求响应都是增加延迟。

[1.] 如果请求的数据量不是超级大(客观上允许响应数据冗余),可以放在一个查询,然后把结果做一次手工聚合

var query = `
    select 
        post.id         as id, 
        post.content    as content, 
        comment.id      as comment_id, 
        comment.content as comment_content, 
        comment.post_id as comment_post_id 
    from      post 
    left join comment on post.id = comment.post_id 
    where post.user_id = ?;
`;

function getListByUserId(userId, callback) {
    function walk(rows) {
        var indexes = {};
        var sets = [];
        var push_comment = function (stack, row) {
            if (typeof row.comment_id === 'number')
                stack.push({
                    id      : row.comment_id,
                    content : row.comment_content,
                    post_id : row.comment_post_id
                });
        };
        var item;
        rows.forEach(function (row) {
            if (row.id in indexes)
                push_comment(sets[indexes[row.id]].comments, row);
            else {
                item = {id:row.id, content:row.content, comments:[]};
                push_comment(item.comments, row);
                indexes[row.id] = sets.length ;
                sets.push(item);
            }
        });
        return sets;
    }

    db.query(query, [userId], function (err, replies) {
        if (err) 
            callback(err, null);
        else 
            callback(null, walk(replies));
    })
}

[2.] 如果数据很大,应该也只分成两个查询,再回来聚合

var mysql = require('mysql');
var query_post    = 'select id, content from post where user_id = ?;';
var query_comment = 'select id, content from comment where post_id = ?;';

function getListByUserId(userId, callback) {
    db.query(query_post, [userId], function (err, replies) {
        if (err) return callback(err, null);
        var query_comments = replies.map(function (reply) {
            return mysql.format(query_comment, reply.id);
        }).join('\n');
        db.query(query_comments, function (err, _replies) {
            if (err) return callback(err, null);
            for (var i = 0, len = _replies.length; i < len; i++)
                replies[i].comments = _replies[i].length > 0 ? _replies[i] : [];
            callback(null, replies);
        })
    });
}
  1. nodejs新手,但上述代码貌似有逻辑错误。手机上的,用PHP代码演示下。
  2. $res=…//SQL查询结果
  3. foreach($res as $k =<> $v){ $v[“aaa”]=123;//这样的赋值方式,不能影响$res. } post.comments=comments;cu错误。 改喂为,posts.comments=comments;

万恶的输入框,删除不掉。。 f $er

感觉4楼也对,看来异步改变不止是体验,还有代码执行顺序问题啊。如此,所,此处return,需要基,事件驱动? 万恶的输入框,真删除不掉啊。。。

回到顶部