
实现代码 github 最近在做一个项目涉及到 mongoose 的关联查询等等,之前做的 mysql,postgresql 比较多,而 mongoose 用的都是比较简单的存储数据,简单查询等等。 刚开始涉及 ref 还是有点小晕的,查询了相关资源,也可以模模糊糊做出来,但是会有各种报错。痛下决心研究透彻点,晚上熬夜到 2 点终于有点小眉目了。
- node v8.5.0
- mongodb
- 结合一个接口理解
- 结合 promise-async-await
- 一般采用 mvc 模式,本文就直接在 express 里直接写了
直接使用了 express -e mongoose-ref
const mOngoose= require('mongoose'); mongoose.connect('mongodb://localhost:27017/ref'); 同时建立关联 user->city->state->country
const Schema = mongoose.Schema; const ObjectId = Schema.Types.ObjectId; const UserSchema = new Schema({ username: { type: String }, userpwd: { type: String }, userage: { type: Number }, city: { type: Schema.Types.ObjectId, ref: 'City' }, }); const CitySchema = new Schema({ name: { type: String }, state: { type: Schema.Types.ObjectId, ref: 'State' } }); const StateSchema = new Schema({ name: { type: String }, country: { type: Schema.Types.ObjectId, ref: 'Country' } }); const CountrySchema = new Schema({ name: { type: String } }); const User = mongoose.model('User', UserSchema); const City = mongoose.model('City', CitySchema); const State = mongoose.model('State', StateSchema); const Country = mongoose.model('Country', CountrySchema); const user_getCountryList = async function (req, res) { console.log("/v1/ref start -->" + JSON.stringify(req.body)); try { const respOndData= { status: res.statusCode, data: {}, error: {} }; const username = req.body.username; const userpwd = req.body.userpwd; const userage = req.body.userage; const usercityname = req.body.usercityname; const userstatename = req.body.userstatename; const usercountryname = req.body.usercountryname; const userInfoCountry = await findUserCountry({ name: usercountryname }, usercountryname);//查看国家 const userInfoState = await findUserState({ name: userstatename }, userstatename);//查看州 const userInfoCity = await findUserCity({ name: usercityname }, usercityname);//查看城市 const userInfo = await findUser({ username: username, }, username,userpwd,userage);//查看用户信息 const updateInfoUser = await updateUser({ _id: userInfo },userInfoCity);//更新用户信息 const updateInfoCity = await updateCity({ _id: userInfoCity }, userInfoState);//更新城市信息 const updateInfoState = await updateState({ _id: userInfoState }, userInfoCountry);//更新州信息 return res.json(respondData); } catch (error) { //错误处理 console.log("userCity error -->" + JSON.stringify(error)); respondData.error = error; return res.json(respondData); } } 首先查看传入的国家在 country 中有没有,加入有,返回_id,没有就创建传入的国家名,并返回_id,查看 findUserCountry 函数对应的逻辑
const findUserCountry = async function (cnd, country) { console.log("findUserCountry start --> " + JSON.stringify(cnd)); return new Promise(function (resolve, reject) { Country.findOne(cnd, function (error, data) { console.log("findUserCountry findOne data --> " + JSON.stringify(data)); if (error) { return reject(error); } if (data) { return resolve(data._id); } else { const userCountry = new Country({ name: country }); userCountry.save(function (err, data) { if (err) { console.log("userCountry.save err-->" + JSON.stringify(err)); return reject(err); } console.log("userCountry-->" + JSON.stringify(data)); return resolve(data._id); }); } }); }) } 同理传入的州,城市,用户信息以同样的方式返回_id
通俗的说就是在 User 表中 city 保存 City 表中所需要的_id;也就是之前返回的_id 这时就可以用到,可以参考 updateUser 函数
const updateUser = async function (cnd, cityid) { console.log("updateUser start --> " + JSON.stringify(cnd)); return new Promise(function (resolve, reject) { User.update(cnd, { $set: { city: cityid } }, function (error, data) { console.log("updateUser findOne data --> " + JSON.stringify(data)); if (error) { return reject(error); } return resolve(data); }); }) } 可以使用 postman 模拟数据,如图:
这时就把 City 对应的_id 写进了 User 表中,可以查看表,如图:
同理 user->city->state->country 数据都可以写进不同的表中。
当传入 username 时,使用 populate 关联查询,可以查询出这个人的所以信息
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) { const userInfo = {}; 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); return res.json(respondData); }) }) }); 使用 postman 模拟接口如下 
1 wangweifeng OP 为什么 Markdown 在这里看起来那么怪呢 |
2 qiuyk 2017 年 9 月 22 日 我记得 mongoose 如果 exec 不传 cb 就返回 promise 的吧 既然都用上了 async/await 了 就彻底一点吧 |
3 wangweifeng OP @qiuyk 可以彻底的,最后一句话说了,层层包含还挺好看,或者这也是 js 的一大美感呢,哈哈 |