mongodb一对n关系中的两种导航
Posted
技术标签:
【中文标题】mongodb一对n关系中的两种导航【英文标题】:two way navigation in a mongo one to n relashionship 【发布时间】:2017-12-13 07:55:55 【问题描述】:我在猫鼬 relashionship 系统上遇到了困难。 这是我的计划:
const mongoose = require('mongoose');
const RecipeSchema = mongoose.Schema(
Title: type: String ,
Description: type: String ,
Complaints: [ type: mongoose.Schema.Types.ObjectId, ref: 'Complaint' ]
);
const Recipe = mongoose.model('Recipe', RecipeSchema);
const ComplaintSchema = mongoose.Schema(
Recipe : type: mongoose.Schema.Types.ObjectId, ref: 'Recipe' ,
Message: type: String
);
const Complaint = mongoose.model('Complaint', ComplaintSchema);
以下是我保存数据的方式:
var recipeEntity = new Recipe(
Title: request.body.Title,
Description: request.body.Description
);
recipeEntity.save();
var complaintEntity= new Complaint(
Message: request.body.Message.trim(),
Recipe: mongoose.Types.ObjectId(request.body.Message.RecipeId);
);
complaintEntity.save();
到目前为止,一切都很好……至少对我来说是这样!
现在,当我尝试列出带有投诉的食谱时,我得到的只是一个空的投诉数组:
Recipe
.find()
.populate('Complaints')
.exec(callback);
这是 json 结果:
[
"Id": "595fe6f89d63700011ee144d",
"Title": "Chocolate Cake",
"Description": "aaaa bbb cc d"
"Complaints": []
]
那么,我在这里缺少什么? 感谢您的支持
【问题讨论】:
【参考方案1】:好的,我也不得不将记录保存在参考文献中,我采用了这种方法:
RecipeSchema.pre('remove', function(next)
Complaint.remove( "Recipe" : this._id ).exec();
next();
);
ComplaintSchema.pre('remove', function(next)
Recipe.findById(this.Recipe).exec((error, item) =>
var index = item.Complaints.indexOf(item.Complaints.find(e => e._id == this._id));
item.Complaints.splice(index, 1);
item.save(() => next(); );
);
);
ComplaintSchema.pre('save', function(next)
Recipe.findById(this.Recipe).exec((error, item) =>
item.Complaints.push(this);
item.save(() => next(); );
);
);
使用 mongo 架构上可用的此触发器/事件。 效果很好!
【讨论】:
正确的方法。这通常是使用 mongoose 进行删除级联时要走的路。 tks,希望我的回答也有用【参考方案2】:我将假设您没有在同一次通话中同时保存食谱和投诉。这没有任何意义:每次你提出投诉,你也不会制作食谱。
创建投诉时,您需要保存其关联配方的ObjectId
并且还将投诉的ObjectId
添加/推送到关联配方的投诉中。
如果你关注resource naming conventions,你会得到类似的东西:
// get recipes including complaints
app.get('/recipes', function (req, res)
Recipe.find().populate('Complaints').exec(function (err, recipes)
console.log(recipes);
);
);
// add recipe
app.post('/recipes', function (req, res)
var recipe = new Recipe(req.body); // simplified
recipe.save(function (err)
if (err)
return res.send(err);
res.send('ok');
);
);
// add complaint for recipe
app.post('/recipes/:recipeID/complaints', function (req, res)
// we query recipe bc we need it after
Recipe.findById(req.params.recipeID, function (err, recipe)
if (err)
return res.send(err);
if (!recipe)
return res.send('No recipe found');
// add complaint
var complaint = new Complaint(req.body);
complaint.Recipe = recipe._id; // add reference in one direction
complaint.save(function (err)
if (err)
return res.send(err);
// update recipe
recipe.Complaints.push(complaint._id); // add reference in other direction
recipe.save(function (err)
if (err)
return res.send(err);
res.send('ok');
);
);
);
)
我认为这是一本好书:many to many relationship with nosql (mongodb and mongoose)。
【讨论】:
Tks。受到您的解决方案的启发,我在下面开发了该解决方案并在此处发布以帮助遇到类似问题的人。以上是关于mongodb一对n关系中的两种导航的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB 中的关联查询MongoDB : aggregate/lookup 对比 Mongoose : ref / populate