mongoose-ref
實現程式碼github
最近在做一個專案涉及到mongoose的關聯查詢等等,之前做的mysql,postgresql比較多,而mongoose用的都是比較簡單的儲存資料,簡單查詢等等。
剛開始涉及ref還是有點小暈的,查詢了相關資源,也可以模模糊糊做出來,但是會有各種報錯。痛下決心研究透徹點,晚上熬夜到2點終於有點小眉目了。
- node v8.5.0
- mongodb
- 結合一個介面理解
- 結合promise-async-await
- 一般採用mvc模式,本文就直接在express裡直接寫了
1. 首先建立了一個mongoose-ref專案
直接使用了express -e mongoose-ref2.在routes/index裡連線mongodb資料庫
const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost:27017/ref');複製程式碼
3.建立4個模型,使用者:User,城市:City,省份:State,國家:Country
同時建立關聯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);複製程式碼
4.主要採用promise-async-async進行邏輯處理
首先建立一個user_getCountryList函式,如下程式碼
首先檢視傳入的國家在country中有沒有,加入有,返回_id,沒有就建立傳入的國家名,並返回_id,檢視findUserCountry函式對應的邏輯
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); } }複製程式碼
同理傳入的州,城市,使用者資訊以同樣的方式返回_id
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); }); } }); }) }複製程式碼
接下來就要進行關聯user->city->state->country
通俗的說就是在User表中city儲存City表中所需要的_id;也就是之前返回的_id這時就可以用到,可以參考updateUser函式可以使用postman模擬資料,如圖:
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); }); }) }複製程式碼
這時就把City對應的_id寫進了User表中,可以檢視錶,如圖:
同理user->city->state->country資料都可以寫進不同的表中。
5.使用populate關聯查詢
當傳入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模擬介面如下