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'
的记录。