mongodb中连表查询很方便,mongoose中的populate可以很方便的实现
mongodb
中连表查询很方便,mongoose
中的populate
可以很方便的实现
一、参考一
const User = mongoose.Schema({
role: String, // 角色
name: String, // name
pass: String,
avatar: {
type: ObjectId, //联表查询必须这样的格式来存储对应表的._id
ref: 'File' // //联表关系的表名: avatar关联着File中的id -> file id
},
type: { type: String },
deleted: { type: Boolean, default: false },
create_time: { type: Number, default: getTime },
update_time: Number,
correlate: ObjectId
});
// File中有name,path等属性
var FileSchema = mongoose.Schema({
name : String, //名称
original_name : String,
path : String, //路径
size : Number,
type : String,
creator : {type: ObjectId, ref: 'Admin'},
deleted : {type: Boolean, default: false},
create_time : {type: Date, default: Date.now}
});
现在,这两张表是关联表,查询User
的时候如何关联查询出File
中的所有属性呢? 如下是一个查询接口的实现,根据user name
查询出user
和关联的File
所有数据:
const User = mongoose.model('User');
const user = await User.findOne({name: args.name})
//populate()第一个参数表示通过什么字段去联表并用来放入查到的联表数据,
//populate()第二个参数表示只返回某个字段, 默认全部返回
.populate('avatar', {name: 1})
.exec();
return {
code: code.success,
data: {
user: {
name: user.name,
role: user.role,
create_time: user.create_time,
_id: user._id,
avatar: user.avatar
}
}
};
可见,File
通过连表查询populate
查询出了File
所有的数据。 populate
函数还有其他参数:
populate('avatar', {name: 1})
表示只返回File
的name
属性,不返回其他属性。
二、参考二
数据库简单的增删改查是很容易但是真正到了项目中有些地方就需要两张甚至多张表进行关联,这样的话难度瞬间上了一个档次。
模型层
因为要联表所以要建立两个模型,这边我们要做的是通过**order**
表去查询**user**
表的参数。
order
const Mongoose = require('mongoose')
const order = new Mongoose.Schema({
orderNum: String,
user: String,
userName: {
type: Mongoose.Schema.Types.ObjectId,//联表查询必须这样的格式来存储对应表的._id
ref: 'user'//联表关系的表名
}
})
module.exports = Mongoose.model('order',order)
这里的重点就在order
模型中定义的userName
。
字段的类型是Mongoose.Schema.Types.ObjectId
是mongodb的集合中每条数据默认存在的_id
类型,ref
是要关联的集合模型。
user
const Mongoose = require('mongoose')
var user = new Mongoose.Schema({
user: String,
age: String,
inter: Object
})
module.exports = Mongoose.model('user',user)
没什么好说的普通的模型创建。
控制层
const user = require('../model/user')
const order = require('../model/order')
存储
var userTest = new user({
user: '测试名字',
age: 29,
inter: {
sport: 'football',
eat: 'apple'
}
})
userTest.save(function (err,res) {
if (err) {
console.log(err,'错误了')
} else {
console.log('创建集合成功',res)
var orderTest = new order({
orderNum: '12354645',
user: '测试名字',
userName: res._id//用来存储关联表查出的数据
})
orderTest.save()
}
})
先执行存储,先存user
数据然后在成功的回调中存order
数据(因为要拿到存储user
数据的_id
),将user
数据的_id
设置到order
数据的userName
中。
查询
var a = await order.find({user: '测试名字'})
//populate()第一个参数表示通过什么字段去联表并用来放入查到的联表数据,
//populate()第二个参数表示只返回某个字段默认全部返回
.populate('userName','age')
// .exec(function (err,data) {
// console.log(data)
// })
//exec()是回调操作没有exec()操作才能打印出完整a
console.log('我是a',a)
通过mongoose
模型的.populate
来联表查询。大致的流程可以理解成一下三步:
1、先查询到order
表的{user: '测试名字'}
这条数据
2、通过这条数据中的userName
中的_id
去找user
表中的相同_id
的那条数据
3、查询到后将查询到的数据放到userName
(相当于将原本字段中的_id
替换成查询到的user
表数据)。
查询结果
联表查询和存储是很重要的功能在项目中肯定会用到这里先记录下。
三、参考三
建立的实例场景为一个聊天室中可以有多名用户。
创建数据
建立用户原型
// Users.js
const mongoose = require('mongoose')
// Schema: 数据库骨架, 不能操作数据库
const Schema = mongoose.Schema
var UserSchema = new Schema({
_id: Number,
name: String,
sex: String
})
// Model: 由Schema发布生成的模型, 具有抽象性和对数据库操作的行为
var User = mongoose.model('users', UserSchema)
// 将原型和方法编译为一个模块
建立聊天室原型
// Room.js
var RoomSchema = new Schema({
roomNumber: String,
roomMember:[{
type: Number,
ref: 'users'
}]
})
var Room = mongoose.model('rooms', RoomSchema)
// 将原型和方法编译为一个模块
分别创建实例,并将数据存入数据库
// 1. 创建实例
var lily = new User({'_id':1000, 'name': 'lily', sex: 'F'});
var lucy = new User({'_id':1001, 'name': 'lucy', sex: 'F'});
var room = new Room({
'roomNumber': '1',
// 此处所调用的必须为_id字段
'roomMember': [lily._id, lucy._id]
})
// ...
// 2. 存入数据库
function callback(err, doc) {
if(err) throw err;
console.log(doc); // 返回的是存入数据库中的记录
}
lily.save(callback)
lucy.save(callback)
room.save(callback)
数据库中的查询记录如下:
使用 population
进行联表查询
我们可以通过聊天室去查询用户信息:
Room.findOne({ roomNumber: '1' })
.populate('roomMember')
.exec(callback)