Nodejs mongoose怎么populate别的集合的子文档?
Nodejs mongoose怎么populate别的集合的子文档?
ASchema = new mongoose.Schema({
name: String,
B: [BSchema]
});
var BSchema = new Schema({
name: String
});
var CSchema = new Schema({
name: String,
B: {
type: Schema.ObjectId,
ref: ‘BSchema’
}
});
//This is OK, but not one time mongoose search:
CSchema.find({
name: ‘C_xxx’
}).exec(function(err, docC) {
docC.forEach(function(o) {
var BId = o.B;
A.findOne({
‘B._id’: BId
}, {
‘B.$’: 1
}
).exec(function(err, docA) {
var Bname = docA.B[0].name;
var Cname = docA.name;
});
});
});
//wrong in populate:
CSchema.find({
name: ‘C_xxx’
})
.populate(‘ASchema.B’)
.exec(function(err, docC) {
docC.forEach(function(o) {
var Bname = o.B.name;
//ERROR:o.B is a objectId,o.B.name is undefined
//Aname can’t find
});
});
I can’t find it with populate, o.B is a objectId,o.B.name is undefined.
BSchema is a subdocument of ASchema, CSchema has a ref connection of BSchema.
Data like this:
ASchema = {
name: "A_xxx",
B: [{
_id: 1,
name: "B_xxx"
}, {
_id: 2,
name: "B_xxx"
}]
}
CSchema = [{
name: "C_xxx",
B: 1
}, {
name: "C_xxx",
B: 2
}]
I want to find all CSchema which CSchema’s name is “c_xxx”, and shows CSchema’s B’s name and its A’s name.
Like this result: {CName:“c_xxx”,BName:“b_xxx”,AName:“a_xxx”}
CSchema.find().populate(‘B’).exec();
CSchema.find().populate(‘B’, ‘name’).exec();
我很好奇,既然都能用英文提问,为何不用英文搜索?或者看文档?
B没有单独保存到一个集合里, 是A的子文档, 所以你那样是找不到的 我本来是写成CSchema.find().populate(‘A.B’),但是也不行
要实现通过 populate
方法来查询 CSchema
并获取关联的 BSchema
和 ASchema
的信息,需要进行一些结构调整。根据你的描述,BSchema
是 ASchema
的子文档,而 CSchema
中有一个引用到 BSchema
。
首先,你需要调整 CSchema
中对 B
字段的定义。假设 BSchema
和 ASchema
的结构如你所描述,我们需要确保 CSchema
中的 B
字段是一个引用到 BSchema
的 _id
。
调整后的模型定义
const mongoose = require('mongoose');
const BSchema = new mongoose.Schema({
name: String
});
const ASchema = new mongoose.Schema({
name: String,
B: [BSchema]
});
const CSchema = new mongoose.Schema({
name: String,
B: {
type: mongoose.Schema.Types.ObjectId,
ref: 'BSchema'
}
});
const A = mongoose.model('A', ASchema);
const B = mongoose.model('B', BSchema);
const C = mongoose.model('C', CSchema);
module.exports = { A, B, C };
查询并填充数据
使用 populate
方法来查询 CSchema
并填充 B
引用的数据:
const { C } = require('./models'); // 导入模型
C.find({ name: 'C_xxx' })
.populate({
path: 'B',
populate: {
path: 'B',
model: 'A'
}
})
.exec((err, docs) => {
if (err) {
console.error(err);
return;
}
docs.forEach(doc => {
console.log({
CName: doc.name,
BName: doc.B.name,
AName: doc.B.B[0].name // 注意这里的路径
});
});
});
解释
CSchema
中的B
字段现在是一个ObjectId
,引用到BSchema
。- 使用
.populate
方法填充B
引用的数据。 - 使用嵌套的
populate
填充B
文档中的B
字段(即A
的数据)。
这样,你就可以通过 populate
方法来获取 CSchema
中的所有相关信息,并输出期望的结果。