实现代码 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 模拟数据,如图:
当传入 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 模拟接口如下
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.