当前位置: 首页 > 后端技术 > Node.js

Mongoose的关联操作

时间:2023-04-03 23:31:38 Node.js

mongoose-ref实现代码GitHub最近在做一个项目涉及mongoose的关联查询等。之前有很多mysql和postgresql,但是mongoose使用的是比较简单的数据存储和简单的查询等,一开始看到ref的时候有点晕。查询了相关资源后,大概可以做出来,但是会出现各种错误。我下定决心好好研究一下,一直熬到晚上2点多,总算是有了一点头绪。Nodev8.5.0mongodb结合promise-async-await的接口理解,一般采用mvc模式。本文直接在express中写1。首先建立一个mongoose-ref项目,直接使用express-emongoose-ref2。在routes/index中连接到mongodb数据库constmongoose=require('mongoose');mongoose.connect('mongodb://localhost:27017/ref');3.创建4个模型,user:User,city:City,province:State,country:Country并建立关联user->city->state->countryconstSchema=mongoose.Schema;constObjectId=Schema.Types.ObjectId;constUserSchema=newSchema({username:{type:String},userpwd:{type:String},usage:{type:Number},city:{type:Schema.Types.ObjectId,ref:'City'},});constCitySchema=newSchema({name:{type:String},state:{type:Schema.Types.ObjectId,ref:'State'}});constStateSchema=newSchema({name:{type:String},country:{type:Schema.Types.ObjectId,ref:'Country'}});constCountrySchema=newSchema({name:{type:String}});constUser=mongoose.model('User',UserSchema);常量y=mongoose.model('城市',CitySchema);constState=mongoose.model('State',StateSchema);constCountry=mongoose.model('Country',CountrySchema);4.主要使用promise-async-async进行逻辑处理,首先创建一个user_getCountryList函数,如下代码constuser_getCountryList=asyncfunction(req,res){console.log("/v1/refstart-->"+JSON.字符串化(req.body));try{constrespondData={status:res.statusCode,data:{},error:{}};constusername=req.body.username;constuserpwd=req.body.userpwd;constuserage=req.body.userage;constusercityname=req.body.usercityname;constuserstatename=req.body.userstatename;constusercountryname=req.body.usercountryname;constuserInfoCountry=awaitfindUserCountry({name:usercountryname},usercountryname);//查看国家constuserInfoState=awaitfindUserState({name:userstatename},userstatename);//查看状态constuserInfoCity=awaitfindUserCity({name:usercityname},usercityname);//查看城市constuserInfo=awaitfindUser({username:username,},username,userpwd,userage);//查看用户信息constupdateInfoUser=awaitupdateUser({_id:userInfo},userInfoCity);//更新用户信息constupdateInfoCity=awaitupdateCity({_id:userInfoCity},userInfoState);//更新城市信息constupdateInfoState=awaitupdateState({_id:userInfoState},userInfoCountry);//更新州信息返回res.json(respondData);}catch(error){//错误处理console.log("userCityerror-->"+JSON.stringify(error));respondData.error=错误;返回res.json(respondData);首先检查country中是否存在传入国家,添加,返回_id,如果不存在,则创建传入国家名称,并返回_id,查看findUserCountry函数对应的逻辑constfindUserCountry=asyncfunction(cnd,country){console.log("findUserCountry开始-->"+JSON.stringify(cnd));returnnewPromise(function(resolve,reject){Country.findOne(cnd,function(error,data){console.log("findUserCountryfindOne数据-->"+JSON.stringify(data));if(error){returnreject(error);}if(data){returnresolve(data._id);}else{constuserCountry=newCountry({name:country});userCountry.save(function(err,data){if(err){console.log("userCountry.saveerr-->"+JSON.stringify(err));returnreject(err);}console.log("userCountry-->"+JSON.stringify(data));returnresolve(data._id);});}});})}同样传入的州,城市,用户信息way同理返回_id,接下来就是关联user->city->state->country,通俗地说,User表中的城市保存了City表中需要的_id;即_idreturnbeforeupdateUser函数时可以使用constupdateUser=asyncfunction(cnd,cityid){console.log("updateUserstart-->"+JSON.stringify(cnd));returnnewPromise(function(resolve,reject){User.update(cnd,{$set:{city:cityid}},function(error,data){console.log("updateUserfindOne数据-->"+JSON.stringify(data));如果(错误){返回拒绝(错误);}返回解析(数据);});})}可以使用postman来模拟数据,如图:此时将City对应的_id写入User表,即可查看该表,如图:类似user->city->state->country数据可以写入不同的表5.使用populateassociationquery传入username时,使用populateassociationquery查询此人的所有信息User.find({username:user_name}).populate('city').exec(function(err,docs){City.find({_id:docs[0].city._id}).populate('state').exec(function(err,doc){State.find({_id:doc[0].state._id}).populate('country').exec(function(err,result){constuserInfo={};userInfo.username=docs[0].username;userInfo.userpwd=docs[0].userpwd;userInfo.userage=docs[0].userage;userInfo.usercity=doc[0].name;userInfo.userstate=result[0].name;userInfo.usercountry=result[0].country.name;respondData.data.push(userInfo);返回res.json(respondData);})})});使用postman模拟界面如下。当然,这个关联查询也可以使用promise-async-await,不过有时候看这个回调,包含层的样子还是不错的。或者这也是js的一大美事