mongoose的关联查询 :populate
mongoose关联查询从3.2版本开始支持
基本用法如下:
var studentSchema = new Schema({
name:String,
age:String,
school:{
type:Schema.Types.ObjectId,
ref:'school'
}
}); var schoolSchema = new Schema({
name:String,
students:[
{
type:Schema.Types.ObjectId,
ref:"student"
}
]
}) var Student = mongoose.model('student',studentSchema); var School = mongoose.model("school",schoolSchema); School.findOne({name:"xxx"}).populate("students","name age").exec(function(err,school){
console.log(school);
console.log("============")
}) //populatte中第二个参数,只返回关联表中的字段
Student.findOne({name:"xxx"}).populate("school","name").exec(function(err,student){
console.log(student);
console.log("===============")
})
总结点:
1、schame中的ref值需要对应mongoose.model中的第一个参数,即数据库中的集合名称,否者查询失败
2、populate(arg1,arg2)
第一个参数对应集合中的存续关联数据的属性,若对应错误,查询成功,但关联集合只有_id返回。
第二个参数用于过滤查询关联集合中的属性,多个属性用空格隔开,若缺失,返回关联集合的所有参数,可以传"-_id"去除返回值中的_id属性
注:官方说明:In Mongoose >= 4.0, you can manually populate a field as well.
//官方例子
Story.
findOne({ title: /casino royale/i }).
populate('author', 'name'). // only return the Persons name
exec(function (err, story) {
if (err) return handleError(err); console.log('The author is %s', story.author.name);
// prints "The author is Ian Fleming" console.log('The authors age is %s', story.author.age);
// prints "The authors age is null'
});
3、多个关联集合
Story.
find(...).
populate('fans').
populate('author').
exec();
关于多个关联集合,若同时populate多个相同的集合,则只有最后一个产生作用
School.findOne({name:"xxxx"})
.populate("students","name")
.populate("students","age")
.exec(function(err,school){
console.log(school);
console.log("============")
})
//返回结果中只有age,没有name
//也可以写为:populate({ path: 'students', select: 'name age' })
4、关联条件查询
Story.
find(...).
populate({
path: 'fans',//关联的结合
match: { age: { $gte: 21 }},//条件
select: 'name -_id',//去掉_id属性,选择name
options: { limit: 5 }//分页
}).
exec();
5、多级查询
var userSchema = new Schema({
name: String,
friends: [{ type: ObjectId, ref: 'User' }]
}); User.
findOne({ name: 'Val' }).
populate({
path: 'friends',//查询我的朋友
// Get friends of friends - populate the 'friends' array for every friend
populate: { path: 'friends' }//查询我朋友的朋友列表
});
6、跨数据库查询
var eventSchema = new Schema({
name: String,
// The id of the corresponding conversation
// Notice there's no ref here!
conversation: ObjectId
});
var conversationSchema = new Schema({
numMessages: Number
}); var db1 = mongoose.createConnection('localhost:27000/db1');
var db2 = mongoose.createConnection('localhost:27001/db2'); var Event = db1.model('Event', eventSchema);
var Conversation = db2.model('Conversation', conversationSchema); //给populate的conversation指定一个model,这样就能通过model跨数据库查询
Event.
find().
populate({ path: 'conversation', model: Conversation }).
exec(function(error, docs) { /* ... */ });
7、动态参考:假如有个用户的schema,有个关联的字段为group,group中能来自多个集合的参考,如:group可以是一个足球队、一个篮球队。。。
var userSchema = new Schema({
name: String,
connections: [{
kind: String,
item: { type: ObjectId, refPath: 'connections.kind' }
//connections.kind就是表示此中的关联是kind字段对应的组织
}]
}); var organizationSchema = new Schema({ name: String, kind: String }); var User = mongoose.model('User', userSchema);
var Organization = mongoose.model('Organization', organizationSchema); // 有一个组织{ _id: '01'), name: "Beyond", kind: 'Band' }
//有两个用户
// {_id: '02'),name: '黄家驹',
// connections: [
// { kind: 'User', item: '03') },
// { kind: 'Organization', item:'01') }
// ]
// },
// {
// _id: '03',
// name: '叶世荣',
// connections: []
// } User.
findOne({ name: '黄家驹' }).
populate('connections.item').//关联中的item
exec(function(error, doc) {
// doc.connections[0].item is a User doc
// doc.connections[1].item is an Organization doc
}); //总结:
// refPath告诉mongoose,populate指向connetions.item,
// 而connetions.item又指向connetions.kind,kind最终存的是对应的model,
// kind的值可以不一样,则populate中的指向就会根据kind的值不同而改变,类似动态参数一样
8、虚拟填充:版本>4.5
不是根据_id的关联查询,如下面的例子是关联band名字的关联查询
var PersonSchema = new Schema({
name: String,
band: String
}); var BandSchema = new Schema({
name: String
});
//给BandSchme设置一个虚拟关联字段:members;
BandSchema.virtual('members', {
ref: 'Person', // 虚拟字段的model为Person
localField: 'name', // 查找到Person.band的值和Band.name的值相等的项
foreignField: 'band', //
// justOne用于指定,返回的members是单个数据还是一个数组集合,justOne默认为false
justOne: false
}); var Person = mongoose.model('Person', PersonSchema);
var Band = mongoose.model('Band', BandSchema); /**
* 假如有两个band:"beyond", "唐朝乐队"
* 有4个Person: 黄家驹(黄家驹.band = beyond) 黄家强(黄家强.band="beyond")
* 丁武(丁武.band = "唐朝乐队") 陈磊(陈磊.band="唐朝乐队")
*/
Band.find({}).populate('members').exec(function(error, bands) {
//这里返回的bands含有members字段,里面的值为Person的实例
});
以上基本上是官方文档的所有说明了,需要注意版本的不同。
mongoose的关联查询 :populate的更多相关文章
- Mongoose中关联查询populate的使用
MongoDB中没有join的特性,因此无法使用join进行表的连接和关联查询,在Mongoose中封装了populate方法,在定义一个 Schema 的时候可以指定了其中的字段(属性)是另一个Sc ...
- Mongoose如何实现统计查询、关联查询
[问题]Mongoose如何实现统计查询.关联查询 发布于 4 年前 作者 a272121742 13025 次浏览 最近业务上提出一个需求,要求能做统计,我们设计的文档集,统计可能跨越的文档会 ...
- MongoDB学习day10--Mongoose的populate实现关联查询
一.Mongoose populate官方文档 https://mongoosejs.com/docs/populate.html 二.Mongoose populate关联查询 1.定义ref va ...
- Mongoose 多表(N个表)关联查询aggregate
Mongoose 多表(N个表)关联查询概述 需求:文章(article),文章分类(articlecate),用户(user)这三个表之间的关系,一篇文章对应文章分类表中的某个类型,对应着用户表中的 ...
- Mongoose 两个表关联查询aggregate 以及 Mongoose中获取ObjectId
Mongoose 两个表关联查询aggregate 通常两个表关联查询的时候,是一种一对多的关系,比如订单与订单详情就是一对多的关系,一个订单下面有多个商品 数据模拟 首先我们先将数据模拟出来,先选择 ...
- Mongoose多表查询
文章来自 两个表关联查询aggregate 多个表关联查询aggregate populate多表关联查询 多表查询的两个方式 一个是aggregate聚合 一个是populate Schema的外表 ...
- JDBC MySQL 多表关联查询查询
public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver&q ...
- MYSQL基础操作之数据约束与关联查询
一.MYSQL约束 1.默认值约束,当字段没有插入值的时候,mysql自动给该字段分配默认值. 默认值的字段允许为空. 对默认值字段也可以插入null. CREATE TABLE STUDENT( I ...
- C#代码中实现两个表(DataTable)的关联查询(JOIN)
之前通常都是使用SQL直接从数据库中取出表1和表2关联查询后的数据,只需要用一个JOIN就可以了,非常方便.近日遇到一种情况,两个表中的数据已经取到代码中,需要在代码中将这两个表关联起来,并得到它们横 ...
随机推荐
- Delphi数据库技术中Disablecontrols和Enablecontrols的功能
一般来说,用来扫描整个数据库表并修改每个记录的某一个字段的程序如下所示: with Table Do begin DisableControls;{在修改记录的过程中,使其它部件无效} First; ...
- 正则表达式 re.findall 用法
正则 re.findall 的简单用法(返回string中所有与pattern相匹配的全部字串,返回形式为数组)语法: findall(pattern, string, flags=0) import ...
- phpstudy 安装 Apcahe SSL证书 实现https连接
摘自:https://jingyan.baidu.com/article/64d05a022e6b57de54f73b51.html Windows phpstudy安装ssl证书教程. 工具/原料 ...
- K8S学习笔记之ETCD启动失败注意事项
最近搭建K8S集群遇到ETCD的报错,报错信息如下,一定要关闭防火墙.iptables和SELINUX,三个都要关闭!! Mar 26 20:39:24 k8s-m1 etcd[6437]: heal ...
- c#查找窗口的两种办法
原文最早发表于百度空间2009-06-17 1.process.MainWindowTitle(这个只能获取一部分窗口)2.EnumWindows(用windows API)
- ORA-64379: Action cannot be performed on the tablespace assigned to FastStart while the feature is enabled
解决方法: 禁止IM FastStart exec DBMS_INMEMORY_ADMIN.FASTSTART_DISABLE();
- resmgr:cpu quantum 等待事件 top 1
早上看昨天现场的报告,发现晚上七八点,resmgr:cpu quantum 等待事件排在i第一位,如下: 该事件是和资源管理相关的,如果启用资源管理计划,就可能遇到这个问题. 所以常规的解决方案是禁用 ...
- 【Maven】 Eclipse使用Maven创建Java Web 项目(一)
需求:创建一个Servlet版本3.0,Java版本是1.7的Maven Web项目 创建环境: 系统:window 7 软件:Eclipse.Maven 创建步骤: 1.使用eclipse工具创建m ...
- JavaScript自定义求和函数
我爱撸码,撸码使我感到快乐!大家好,我是Counter,当看到这个标题到时候是不是感觉很简单,千万不要大意哦,你说0.1 + 0.2 = 0.3 ?有时候计算机并不是我们所说绝对精确,这个时候就要我们 ...
- linux shell中如何往所有行尾添加内容
答: sed -i 's/$/yes/' jello.txt 这句话的意思就是在jello.txt文件的所有行尾都添加相同的内容yes,如jello.txt原来的内容为: no jello hello ...