mongodb中连表查询很方便,mongoose中的populate可以很方便的实现
mongodb中连表查询很方便,mongoose中的populate可以很方便的实现
一、参考一
const User = mongoose.Schema({role: String, // 角色name: String, // namepass: String,avatar: {type: ObjectId, //联表查询必须这样的格式来存储对应表的._idref: '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,//联表查询必须这样的格式来存储对应表的._idref: '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()操作才能打印出完整aconsole.log('我是a',a)
通过mongoose模型的.populate来联表查询。大致的流程可以理解成一下三步:
1、先查询到order表的{user: '测试名字'}这条数据
2、通过这条数据中的userName中的_id去找user表中的相同_id的那条数据
3、查询到后将查询到的数据放到userName(相当于将原本字段中的_id替换成查询到的user表数据)。
查询结果

联表查询和存储是很重要的功能在项目中肯定会用到这里先记录下。
三、参考三
建立的实例场景为一个聊天室中可以有多名用户。
创建数据
建立用户原型
// Users.jsconst mongoose = require('mongoose')// Schema: 数据库骨架, 不能操作数据库const Schema = mongoose.Schemavar UserSchema = new Schema({_id: Number,name: String,sex: String})// Model: 由Schema发布生成的模型, 具有抽象性和对数据库操作的行为var User = mongoose.model('users', UserSchema)// 将原型和方法编译为一个模块
建立聊天室原型
// Room.jsvar 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)

