如何在考虑Mongoose Node.js中的引用的情况下删除对象? [英] How to remove object taking into account references in Mongoose Node.js?
问题描述
这是我的MongoDB模式:
This is my MongoDB schema:
var partnerSchema = new mongoose.Schema({
name: String,
products: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Product'
}]
});
var productSchema = new mongoose.Schema({
name: String,
campaign: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Campaign'
}
]
});
var campaignSchema = new mongoose.Schema({
name: String,
});
module.exports = {
Partner: mongoose.model('Partner', partnerSchema),
Product: mongoose.model('Product', productSchema),
Campaign: mongoose.model('Campaign', campaignSchema)
}
我想知道如何在考虑引用的情况下从任何文档中删除对象(也许我应该以某种方式使用猫鼬填充)?例如,如果我将删除Product
,那么我假设我还将同时删除Partner
和属于该Product
的所有Campaigns
中的引用ID.
And I wondering how can I remove object from any document taking into account references (maybe should I use somehow populate from mongoose)? For example if I will remove Product
then I assume that I will remove also ref ID in Partner
and all Campaigns
which belong to this Product
.
此刻,我以这种方式删除:
At the moment I removing in this way:
var campSchema = require('../model/camp-schema');
router.post('/removeProduct', function (req, res) {
campSchema.Product.findOneAndRemove({ _id: req.body.productId }, function (err, response) {
if (err) throw err;
res.json(response);
});
});
但是在mongo中仍然没有引用.
However in mongo still left references.
推荐答案
您必须嵌套调用才能从其他模型中删除产品ID.例如,在您从Product
中删除产品的呼叫中
集合,您还可以再次调用以从结果回调中的Partner
模型中删除该引用.默认情况下删除产品将删除其对Campaign
模型的引用.
You would have to nest your calls to remove the product id from the other model. For instance, in your call to remove the product from the Product
collection, you could also make another call to remove the ref from the Partner
model within the results callback. Removing the product by default will remove its refs to the Campaign
Model.
以下代码显示了上面的直觉:
The following code shows the intuition above:
var campSchema = require('../model/camp-schema');
router.post('/removeProduct', function (req, res) {
campSchema.Product.findOneAndRemove({ _id: req.body.productId }, function (err, response) {
if (err) throw err;
campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } },
function (err, res){
if (err) throw err;
res.json(res);
}
);
});
});
要删除关联的广告系列,那么您可能需要执行额外的删除操作,该操作需要从给定的产品ID中获取关联的广告系列ID.考虑以下肮脏的骇客,如果对回调嵌套不太注意,可能会授予您回调地狱的单程票. :
To remove the associated campaigns then you may need an extra remove operation that takes in the associated campaign id fro a given product id. Consider the following dirty hack which may potentially award you a one-way ticket to callback hell if not careful with the callback nesting:
router.post('/removeProduct', function (req, res) {
campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
{ new: true },
function (err, product) {
if (err) throw err;
campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } },
function (err, res){
if (err) throw err;
var campaignList = product.campaign
campSchema.Campaign.remove({ "_id": { "$in": campaignList } })
.exec(function (err, res){
if (err) throw err;
res.json(product);
})
}
);
}
);
});
尽管有效,但可以使用async/await或 async
中使用多个回调模块,下面以
Although it works, the above potential pitfall can be avoided by using async/await or the async
library. But firstly, to give you a better understanding of the using multiple callbacks with the async
module, let's illustrate this with an example from Seven Things You Should Stop Doing with Node.js of multiple operations with callbacks to find a parent entity, then find child entities that belong to the parent:
methodA(function(a){
methodB(function(b){
methodC(function(c){
methodD(function(d){
// Final callback code
})
})
})
})
使用async/await,您的呼叫将被重组为
With async/await, your calls will be restructured structured as
router.post('/removeProduct', async (req, res) => {
try {
const product = await campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
{ new: true }
)
await campSchema.Partner.update(
{ "products": req.body.productId },
{ "$pull": { "products": req.body.productId } }
)
await campSchema.Campaign.remove({ "_id": { "$in": product.campaign } })
res.json(product)
} catch(err) {
throw err
}
})
使用异步模块,您可以使用系列方法来解决使用回调方法嵌套多个方法的代码,这可能会导致 回调地狱 :
With the async module, you can either use the series method to address the use of callbacks for nesting code of multiple methods which may result in Callback Hell:
系列 :
async.series([
function(callback){
// code a
callback(null, 'a')
},
function(callback){
// code b
callback(null, 'b')
},
function(callback){
// code c
callback(null, 'c')
},
function(callback){
// code d
callback(null, 'd')
}],
// optional callback
function(err, results){
// results is ['a', 'b', 'c', 'd']
// final callback code
}
)
或者 瀑布 :
async.waterfall([
function(callback){
// code a
callback(null, 'a', 'b')
},
function(arg1, arg2, callback){
// arg1 is equals 'a' and arg2 is 'b'
// Code c
callback(null, 'c')
},
function(arg1, callback){
// arg1 is 'c'
// code d
callback(null, 'd');
}], function (err, result) {
// result is 'd'
}
)
现在回到代码,使用异步瀑布方法,然后可以将代码重构为
Now going back to your code, using the async waterfall method you could then restructure your code to
router.post('/removeProduct', function (req, res) {
async.waterfall([
function (callback) {
// code a: Remove Product
campSchema.Product.findOneAndRemove(
{ _id: req.body.productId },
function (err, product) {
if (err) callback(err);
callback(null, product);
}
);
},
function (doc, callback) {
// code b: Remove associated campaigns
var campaignList = doc.campaign;
campSchema.Campaign
.remove({ "_id": { "$in": campaignList } })
.exec(function (err, res) {
if (err) callback(err);
callback(null, doc);
}
);
},
function (doc, callback) {
// code c: Remove related partner
campSchema.Partner.update(
{ "products": doc._id },
{ "$pull": { "products": doc._id } },
function (err, res) {
if (err) callback(err);
callback(null, doc);
}
);
}
], function (err, result) {
if (err) throw err;
res.json(result); // OUTPUT OK
});
});
这篇关于如何在考虑Mongoose Node.js中的引用的情况下删除对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!