Population应该尽量少用吗?我在nodeclub的models中没看到使用ref来做关联,那读取数据的时候怎么做到一次查询
如果是多表查询的话是不行的,具体要在程序里面实现。 Population貌似必须2个表之间有_id关联,可是很多情况貌似满足不了需求。 所以要么在存表的时候给一定的冗余,要么所有的关联在代码中实现(注意一下效率,避免内存溢出)
个人理解,不对勿喷
个人感觉是mongo数据库的集合设计问题 - 内嵌文档 vs. DBRef。如果有两个实体,比如User和Team,约束为M:1(一个Team下可以包含多个User,一个User只能属于一个Team),这种情况下,可以设计为DBRef,集合中数据可能为: User:
{ "_id" : ObjectId("id_of_user#1"), "teamId" : [ { "$ref" : "Team", "$id" : ObjectId("id_of_team#1") } ]}
{ "_id" : ObjectId("id_of_user#2"), "teamId" : [ { "$ref" : "Team", "$id" : ObjectId("id_of_team#1") } ]}
Team:
{ "_id" : ObjectId("id_of_team#1") }
在mongoose中,要定义上述关系,可以这样来定义Schema:
var User = new Schema({
team: { type: Schema.Types.ObjectId, ref: 'Team' },
});
当然还需要导出Schema为Model (mongoose.model(‘User’, User);)。定义Team:
var Team = new Schema({
team: { type: Schema.Types.ObjectId, ref: 'Team' },
});
从数据库里查询User时可以一并查出Team对象:
User.findOne('id_of_some_user')
.populate('team')
.exec(function (err, user) {
// ...
});
这样,user.team就不会是一个ObjectId对象。需要说明的是: 1). 查看数据库会发现,mongoose弄出来的数据和mongodb的官方做法不一样,比如它不是
{ "_id" : ObjectId("id_of_user#1"), "teamId" : [ { "$ref" : "Team", "$id" : ObjectId("id_of_team#1") } ]}
而是
{ "_id" : ObjectId("id_of_user#1"), "teamId" : ObjectId("id_of_team#1") }
这是因为通过Schema的定义,数据的关联关系已经表达得很清楚了。当然,这也可能成为你考虑是否使用mongoose的一个因素(数据活得比应用久,说不定你要考虑换框架呢)。
2). populate会向mongodb数据库发起新的数据库查询,即额外的查询请求(mongodb中并没有关系型数据库的表JOIN操作)。
@GuoZhang 谢谢回复
这样写
var User = new Schema({
team: [{ type: Schema.Types.ObjectId, ref: 'Team' }],
});
生成的就是
{ "_id" : ObjectId("id_of_user#1"), "teamId" : [ { "$ref" : "Team", "$id" : ObjectId("id_of_team#1") } ]}
这样的
既然. populate会向mongodb数据库发起新的数据库查询 ,那应该直接尽量自己写程序解决,populate只是简化了我们查询
不用populate 自己又如何写呢?难道拿到id再查询一次数据库,那结果不是还一样,如果是查询很多数据,要全部遍历一次分别拿id去查一下吗?我只是想知道大家不用populate 怎么处理的 还有populate 这个好像只能查询直接关联的model,关联的model的关联model就不能查询出来了,怎么办呢?
@hanzel21cn 你说的所在的关联在代码中实现是如何做的?可以做到多级关联查询吗?
@GuoZhang 知道如何实现多级关联查询吗?
找到了,最新版的mongoose支持了deep-populate 官方文档: deep-populate