这是我的猫鼬模式:
var SchemaA = new Schema({
field1: String,
.......
fieldB : { type: Schema.Types.ObjectId, ref: 'SchemaB' }
});
var SchemaB = new Schema({
field1: String,
.......
fieldC : { type: Schema.Types.ObjectId, ref: 'SchemaC' }
});
var SchemaC = new Schema({
field1: String,
.......
.......
.......
});
当我使用查找查询访问架构 A 时,我想拥有字段/属性模式 A 以及模式 B 和架构 C,就像我们在 SQL 数据库中应用连接操作一样。
这是我的方法:
SchemaA.find({})
.populate('fieldB')
.exec(function (err, result){
SchemaB.populate(result.fieldC,{path:'fieldB'},function(err, result){
.............................
});
});
上面的代码运行良好,但问题是:
- 我想通过架构 A 获得 SchemaC 的信息/属性/字段,并且我不想填充 SchemaB 的字段/属性。
- 不想获取 SchemaB 属性的原因是,额外的填充将减慢不必要的查询速度。
长话短说:我想通过架构 A 填充架构 C,而不填充架构 B。
你能建议任何方式/方法吗?
作为一个狂热的mongodb粉丝,我建议你使用关系数据库来处理高度关系的数据 - 这就是它的目的。 当您必须执行 3+ 查询以获取单个对象时,您将失去 mongodb 的所有好处。
Buuuuuut,我知道这个评论会被置若罔闻。 你最好的选择是尽可能有意识地关注表现。第一步是将字段限制为所需的最小值。 即使使用基本查询和任何数据库引擎,这也是很好的做法 - 仅获取所需的字段(例如。 SELECT * FROM
=== 不好...别再做了! 您还可以尝试执行精益查询,以帮助节省猫鼬对数据所做的大量后处理工作。 我没有测试这个,但它应该可以工作...
SchemaA.find({}, 'field1 fieldB', { lean: true })
.populate({
name: 'fieldB',
select: 'fieldC',
options: { lean: true }
}).exec(function (err, result) {
// not sure how you are populating "result" in your example, as it should be an array,
// but you said your code works... so I'll let you figure out what goes here.
});
此外,一种非常"mongo"的方法来执行您想要的操作,方法是将 SchemaC 中的引用保存回 SchemaA。 当我说"mongo"的方式时,你必须摆脱你多年来对关系数据查询的思考。 尽一切努力对数据库执行更少的查询,即使它需要双向引用和/或数据重复。
例如,如果我有一个书籍架构和作者架构,我可能会将作者的名字和姓氏保存在"书籍"集合中,以及"作者"集合中对完整配置文件的_id引用。 这样,我可以在单个查询中加载我的书籍,仍然显示作者的姓名,然后生成指向作者个人资料的超链接:/author/{_id}
.这被称为"数据非规范化",众所周知,它会给人们带来胃灼热。我尝试将其用于不经常更改的数据 - 例如人们的名字。在名称确实更改的情况下,编写一个函数来更新多个位置的所有名称是微不足道的。
SchemaA.find({})
.populate({
path: "fieldB",
populate:{path:"fieldC"}
}).exec(function (err, result) {
//this is how you can get all key value pair of SchemaA, SchemaB and SchemaC
//example: result.fieldB.fieldC._id(key of SchemaC)
});
为什么不添加一个ref
SchemaC
SchemaA
? 如果没有像您当前拥有它的方式SchemaB
,则无法从SchemaA
桥接到SchemaC
,除非您填充SchemaB
除了要SchemaC
ref
之外没有其他数据
如"字段选择"下的文档中所述,您可以限制返回的字段。 .populate('fieldB')
变得populate('fieldB', 'fieldC -_id')
.-_id 需要省略_id字段,就像使用 select()
一样。
我认为这是不可能的。因为,当 A 中的文档引用 B 中的文档并且该文档引用 C 中的另一个文档时,A 中的文档如何在没有 B 帮助的情况下知道要从 C 引用哪个文档。