Nodejs+mongodb联表查询问题
Nodejs+mongodb联表查询问题
我现在有两个表 一个question { “name” : “test”, “faq” : “faq”, “_id” : ObjectId(“521dac0e5a5be3f81e000002”), }
一个info { “name” : “test”, “imgUrl” : “./public/images/11.jpg”, "_id" : ObjectId(“521dac2b5a5be3f81e000004”) }
我的需求是,查询question中的name,然后还有知道name的头像地址,所以要二次查询info中imgUrl
mongodb.open(function(err, db){
if(err){
return callback(err);
}
//读取 users 集合
db.collection(‘question’, function(err, collection){
if(err){
mongodb.close();
return callback(err);
}
//查找用户名 name 值为 name文档
collection.find({hide:{$ne:false}}).limit(5).sort({time:-1}).toArray(function(err,items){
if(err) throw err;
//二次查询
db.collection('info', function(err, collection){
for(var i=0,l=items.length;i<l;i++){
collection.find({name:items[i].name}).toArray(function(err,itens){
var l;
});
}
});
mongodb.close();
//遍历数据
return callback(items);
});
});
});
这里在查询到collection.find({name:items[i].name}).toArray(function(err,itens){var l;}); 时,这里查询失败,断点始终进入不了var l;上
我用第二种方法有尝试,就是
mongodb.open(function(err, db){
if(err){
return callback(err);
}
//读取 users 集合
db.collection(‘question’, function(err, collection){
if(err){
mongodb.close();
return callback(err);
}
//查找用户名 name 值为 name文档
collection.find({hide:{$ne:false}}).limit(5).sort({time:-1}).toArray(function(err,items){
if(err) throw err;
mongodb.close();
//遍历数据
return callback(items);
});
});
});
这个查询完后,我先把items中的name放到一个数组,然后 再次打开mongodb.open 遍历查找
这样两种查询都无法二次查到info 表里面的内容,每次都是collection.find() 这里出错
求大神帮助
在Node.js中使用MongoDB进行联表查询时,确实需要处理异步操作。你遇到的问题主要是由于异步操作导致的数据未准备好就被访问了。我们可以使用Promise或者async/await来更好地管理异步操作。
以下是一个改进后的示例代码,展示了如何使用async/await
来实现你的需求:
const MongoClient = require('mongodb').MongoClient;
const url = 'mongodb://localhost:27017'; // 替换为你的MongoDB连接字符串
async function getQuestionWithAvatar() {
let client;
try {
client = await MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true });
const db = client.db('yourDatabaseName'); // 替换为你的数据库名
const questions = await db.collection('question').find({ hide: { $ne: false } }).limit(5).sort({ time: -1 }).toArray();
const promises = questions.map(async (question) => {
const info = await db.collection('info').findOne({ name: question.name });
return { ...question, imgUrl: info ? info.imgUrl : null };
});
const result = await Promise.all(promises);
return result;
} catch (err) {
console.error(err);
} finally {
if (client) {
client.close();
}
}
}
getQuestionWithAvatar().then(result => {
console.log(result);
}).catch(error => {
console.error(error);
});
解释
- 连接数据库:使用
MongoClient.connect
来连接到MongoDB数据库。 - 查询问题集合:使用
find
方法查询question
集合,并限制结果数量、排序。 - 并行查询信息:使用
map
和Promise.all
来并行处理每个问题,查询对应的info
集合。 - 合并结果:将查询到的信息合并到问题对象中,返回最终结果。
- 错误处理:使用
try/catch
块来捕获可能的错误。 - 关闭连接:确保在完成所有操作后关闭数据库连接。
这种方法利用了async/await
来简化异步操作的处理,避免了回调地狱,并且能够正确地等待所有的查询完成后再返回结果。
自己解决了 异步的坑 db.collection(‘info’, function(err, collection){
for(var i=0,l=items.length;i<l;i++){
collection.find({name:items[i].name}).toArray(function(err,itens){
var l;
});
}
});
mongodb.close();
这个 mongodb.close();在链接info时就执行了,当具体循环时,mongodb已经关闭,所以无法查询
另外一个坑:
for(var i=0,l=items.length;i<l;i++){
collection.find({name:items[i].name}).toArray(function(err,itens){
var l;
});
}
这个循环异步发出,var l;断点这个是谁先查到数据,谁先返回。
表设计不够好,将这两个信息放在一起 会有什么问题么
恩~第一次用mongodb,都是摸索着用,
这两个表一个是用户提问题,记录问题的表, 一个是用户注册存放用户信息的表
针对你的需求,可以在 Node.js 中使用 MongoDB 的聚合框架来实现联表查询。不过,由于 MongoDB 是文档型数据库,它不支持传统的 SQL 联表查询,但可以使用 $lookup
操作符来模拟类似的功能。
以下是一个示例代码,展示如何使用 MongoDB 的聚合框架来实现你的需求:
const MongoClient = require('mongodb').MongoClient;
const uri = 'mongodb://your_connection_string';
MongoClient.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true }, (err, client) => {
if (err) {
console.error('Failed to connect to MongoDB:', err);
return;
}
const db = client.db('your_database_name');
db.collection('question')
.aggregate([
{
$match: { hide: { $ne: false } }
},
{
$sort: { time: -1 }
},
{
$limit: 5
},
{
$lookup: {
from: 'info',
localField: 'name',
foreignField: 'name',
as: 'userInfo'
}
},
{
$unwind: '$userInfo'
},
{
$project: {
name: 1,
faq: 1,
imgUrl: '$userInfo.imgUrl'
}
}
])
.toArray((err, result) => {
if (err) {
console.error('Error executing aggregation:', err);
return;
}
console.log(result);
client.close();
});
});
解释
- 连接到 MongoDB:首先连接到 MongoDB 数据库。
- 聚合操作:
- 使用
$match
过滤hide
字段不等于false
的文档。 - 使用
$sort
按time
字段降序排列。 - 使用
$limit
限制返回的结果数量。 - 使用
$lookup
将question
和info
集合关联起来。localField
是question
集合中的字段名,foreignField
是info
集合中的字段名,as
是结果字段名称。 - 使用
$unwind
将数组结果展开成单个文档。 - 使用
$project
来指定输出字段,包括name
,faq
和从info
集合获取的imgUrl
。
- 使用
- 处理结果:将查询结果打印出来,并关闭数据库连接。
这种方法避免了多次查询数据库的开销,提高了性能。