求姿势!关于nodejs mysql的嵌套查询问题
发布于 8 年前 作者 lxsky1994 6724 次浏览 来自 问答

刚接触nodejs不久,最近使用express框架做一个api平台。使用了Mysql数据库。然而,在MYSQL查询的时候,遇到了一个问题解决不了。

要实现的功能: 查询项目列表信息(project表),并且同时返回用户的昵称,头像(user表)。

问题描述: 要返回的总数组为datas。在第一次SQL查询中,成功获得了project表的所有信息,然后,遍历每一条记录,并且获取每一条记录所属的用户ID,第二次SQL查询则是根据用户ID来获取nickname和avatar。然后合并。最后返回。

但是现在出现问题:返回的结果,只是第一次查询的内容数组。第二次的没有合并成功。 虽然通过联合查询可以实现该功能,但是在其他地方还是遇到了这个问题,并且没法使用联合查询。所以迫切的需要解决该问题。

============================================= project表: id user_id title content

user表: id nickname avatar

我最先开始是使用了2个select语句来实现。但是无法把user表的信息组合到总信息数组中。代码如下: exports.recommendList = function(req, res){ res.setHeader(‘Content-Type’, ‘application/json;charset=utf-8’); res.setHeader(‘Access-Control-Allow-Origin’, '’); var user_id =’’; var page = parseInt(req.params.page); var pagesize = 3; var offset = pagesize(page-1); var sql = “select * from project where status!=0 and recommend =1 order by id desc limit “+offset+”,”+pagesize;

conn.query(sql,function(err,rows){
    if (err) {
        console.log(err);
    }else{
            var i = 0;
            var datas = new Array();
            rows.forEach(function(row){
                var user_id = row.user_id;
                var user_sql = "select avatar,nickname from user where id="+user_id;
                conn.query(user_sql,function(err,result){
                    if (err) {
                        console.log(err);
                    }else{
                        var nickname = result[0].nickname;
                        var avatar = result[0].avatar;
                        console.log("nickname="+nickname);
                        console.log("avatar="+avatar);
                        row.nickname = nickname;
                        row.avatar = avatar;
						console.log(row);     //这里合并成功
                    }
                })
                datas[i]=row;                  //这里不显示合并后的结果。只显示第一次查询后的结果
                i++;
            })
            console.log(datas);
            res.json({code: 200,content:datas})
    }
});

};

5 回复

请使用async库或promise等异步流程处理库

来自酷炫的 CNodeMD

@o6875461 这方面的资料好少。搜索async,很多结果都只是一个async.eachSeries的示例例子,可以顺序执行。但是返回值怎么弄呢

async呢,你可以这样用

//存储查询的sql语句的数组
let sqlArr = [];
//存储查询结果的对象
let resObj = {};
async.eachSeries(sqlArr, function(item, callback){
	db.query(item, function(err, rows){
		if(err){
			return callback(err);
		}
		resObj[item] = rows;
		callback(null);
	}));
},function(err) {
	if(err){
		return console.error(err)
	}
	//对结果进行处理...结果均在resObj中,key为sql语句,value为语句对应的sql执行结果
	console.log(resObj);
});

接楼上,但是async库在现在co和promise都存在的情况下,意义已经没有那么大了,你也可以发现,上面的代码虽说解决了一定的cb嵌套,但是还是很难看,下面是promise的写法

//首先你要把db.query封装成一个promise,如下:
//这部分代码你可以放到公共lib文件里面
function query(sql){
	return new Promise(function (resolve, reject){
		db.query(sql, function(err, rows){
			if(err)
				return reject(err);
			relsolve(rows);
		});
	});
}

//下面是主逻辑
//存储查询的sql语句的数组
let sqlArr = [];
//构造一个promiseArr存储所有的db查询promise对象
let promiseArr =sqlArr.map(item=>query(item));
//使用Promise.all方法执行;then中的dataArr即为查询的结果,顺序和sqlArr中的sql一致,处理逻辑可以放在这里;最后的catch是异常捕获,异常处理放在这里
Promise.all(promiseArr).then(dataArr=>console.log(dataArr)).catch(err=>console.error(err));

两表联查不行吗?这种问题不应该在node里面处理。 select * from project p left join user u on p.userid = u.userid;

回到顶部