Nodejs mongoose 查询问题
Nodejs mongoose 查询问题
var a = new Schema({ name: ‘’, b_id: {type: Schema.ObjectId, ref: ‘b’} });
var b = new Schema({ name: ‘’, });
a: {name: ‘1’, b_id: ‘…’} {name: ‘2’, b_id: ‘…’} {name: ‘3’, b_id: ‘…’}
b: {name: ‘b1’} {name: ‘b2’} {name: ‘b3’}
a.find({}) .populate({ path: ‘b_id’, match: {‘name’: ‘b1’} }) .exec(callback);
怎么实现Inner Join ??
在 Node.js 中使用 Mongoose 进行查询时,我们通常会用到 populate 方法来处理引用(reference)字段。你的需求是实现类似 SQL 的内连接(INNER JOIN),这可以通过组合多个条件来完成。
首先,让我们理解一下你提供的模型定义和数据结构:
模型定义
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const bSchema = new Schema({
name: String,
});
const aSchema = new Schema({
name: String,
b_id: { type: Schema.Types.ObjectId, ref: 'B' } // 注意这里 ref 应该大写 B
});
const A = mongoose.model('A', aSchema);
const B = mongoose.model('B', bSchema);
数据
假设我们有以下数据:
b集合包含三个文档:{ name: ‘b1’ }, { name: ‘b2’ }, { name: ‘b3’ }a集合包含三个文档,每个文档都有一个b_id引用b集合中的文档
查询实现 INNER JOIN
Mongoose 的 populate 方法默认执行的是左连接(LEFT JOIN)。如果你需要实现内连接(INNER JOIN),可以先筛选 b 集合,然后将结果作为条件传递给 populate 方法。
B.find({ name: 'b1' }, (err, bResults) => {
if (err) return console.error(err);
const bIds = bResults.map(b => b._id);
A.find({ b_id: { $in: bIds } })
.populate('b_id')
.exec((err, aResults) => {
if (err) return console.error(err);
console.log(aResults);
});
});
解释
- 查找
b集合中符合条件的文档:首先通过B.find()获取所有name为 ‘b1’ 的文档。 - 获取这些文档的
_id:从结果中提取出b_id列表。 - 在
a集合中查找与这些b_id匹配的文档:使用A.find()查找b_id在之前获取的bIds列表中的所有文档。 - 填充
b_id字段:最后使用populate('b_id')将b_id字段替换为对应的b文档。
这种方法实际上实现了类似于 SQL 中的内连接(INNER JOIN)的效果,因为它只返回那些在 a 和 b 集合中都存在的记录。
mongodb 的特点就是不支持 inner join
一般遇到关系数据库中jion这样的情景,尽量设计成内嵌文档,或者是局部数据的内嵌。
最没办法的情况就是,先查主文档,然后for循环查另外一个文档。
嗯好谢谢。
在Mongoose中,使用populate()方法可以实现类似于SQL中的INNER JOIN的效果。根据你的描述,你已经定义了两个Schema(a和b),并且a模型中的b_id字段引用了b模型。
根据你的需求,你想要查询所有a文档,并且只返回那些关联的b文档中name字段等于'b1'的记录。你可以通过populate()方法来实现这一点,具体代码如下:
a.find({}) // 查询所有a文档
.populate({
path: 'b_id', // 关联b_id字段
match: {'name': 'b1'}, // 只填充name为'b1'的b_id
select: 'name' // 只选择需要的字段,这里选择name字段
})
.exec((err, result) => {
if (err) return console.error(err);
console.log(result);
});
解释
a.find({}):查询所有a文档。.populate({...}):填充关联的b_id字段。path: 'b_id':指定要填充的字段名。match: {'name': 'b1'}:指定匹配条件,只有b文档中name字段值为'b1'的才会被填充。select: 'name':指定只选择b文档中的name字段,这样可以减少返回的数据量。
.exec(callback):执行查询并调用回调函数处理结果。
以上代码会返回所有满足条件的a文档,并且每个文档中b_id字段对应的b文档将仅包含name字段等于'b1'的记录。

