Node.js从关联元素中删除元素

时间:2017-05-13 21:20:29

标签: javascript node.js mongoose

我添加了一项功能,用户可以在其个人资料中添加食谱。但是,当删除配方时,即使它没有出现在用户的显示页面上,该配方也不会从用户的pinnedRecipes中删除(该ID保留在用户& #39; s数据库中的pinnedRecipes。

这里是食谱和用户的pinnedRecipes之间的关联:

var userSchema = new mongoose.Schema({
    username: String,
    password: String,
    admin: {type:Boolean, default: false},
    bio: {type:String, default: "Cet utilisateur n'a pas encore rempli cette section."},
    profileImage: {type:String, default: "http://www.wilwia.com/images/default-user.png"},
    pinnedRecipes:[
        {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Recipe"
        }
    ]
});

var recipeSchema = new mongoose.Schema({
    title: String,
    source: String,
    image: String,
    preplength: String,
    cooklength: String,
    portions: Number,
    description: String,
    ingredients: String,
    instructions: String,
    createdAt: { type: Date, default: Date.now },
    author: {
        id: {
            type: mongoose.Schema.Types.ObjectId,
            ref: "User"
        },
        username: String,
    },
    comments: [
            {
                type: mongoose.Schema.Types.ObjectId,
                ref: "Comment"
            }
        ],
    category: {type:String, enum: ['appetizer', 'salad', 'soup', 'meat', 'pasta', 'breakfast', 'dessert']}
});

这是我尝试过的,没有用的(一切正常,除了从pinnedRecipes中移除配方):

    //DESTROY ROUTE
router.delete("/:id", middleware.checkRecipeOwnership, function(req, res){
    Recipe.findById(req.params.id, function(err, foundRecipe){
        if(err){
            res.redirect("back");
        } else {
            //delete associated comments
            if(foundRecipe.comments.length > 0){
                Comment.remove({
                _id: {
                    $in: foundRecipe.comments
                }
            }, function(err){
                if(err){
                    console.log(err);
                }
            });
            //delete from every user's pinned recipes
            User.find({pinnedRecipes: "ObjectId(" + foundRecipe._id + ")"}, function(err, foundUsers){
                if(err){
                    console.log(err);
                } else {
                    console.log(foundUsers);
                    foundUsers.forEach(function(user){
                        user.pinnedRecipes.remove(foundRecipe);
                        user.save();
                    });
                }
            });
            //remove the campground
            foundRecipe.remove(function(err, recipe){
               if(err){
                   console.log(err);
                   res.redirect("/recipes");
               } else {
                   res.redirect("/recipes");
               }
            });
            }
        }
    });
});

另外,这里有如何固定食谱:

// PIN ROUTE
router.get("/pin/:id", middleware.isLoggedIn, function(req, res){
    Recipe.findById(req.params.id, function(err, foundRecipe){
        if(err){
            req.flash("error", "Une erreur s'est produite.");
            res.redirect("/recipes/" + foundRecipe._id);
        } else {
            User.findById(req.user._id, function(err, user){
                if(err){
                    req.flash("error", "Une erreur s'est produite.");
                    res.redirect("/recipes/" + foundRecipe._id);
                } else { 
                  user.pinnedRecipes.push(foundRecipe);
                  user.save();
                  res.redirect("/recipes/" + foundRecipe._id);
                  req.flash("success", "Pinned recipe"); 
                }
            });
        }
    });
});

// UNPIN ROUTE
router.delete("/pin/:id", middleware.isLoggedIn, function(req, res){
    Recipe.findById(req.params.id, function(err, foundRecipe){
        if(err){
            req.flash("error", "Une erreur s'est produite.");
            res.redirect("/recipes/" + foundRecipe._id);
        } else {
            User.findById(req.user._id, function(err, user){
                if(err){
                    req.flash("error", "Une erreur s'est produite.");
                    res.redirect("/recipes/" + foundRecipe._id);
                } else { 
                  user.pinnedRecipes.remove(foundRecipe);
                  user.save();
                  res.redirect("/recipes/" + foundRecipe._id);
                  req.flash("success", "Pinned recipe"); 
                }
            });
        }
    });
});

非常感谢!

1 个答案:

答案 0 :(得分:0)

我发现您的代码有两个问题:

  • 您正在进行2次异步操作,而不是真正等待其响应。始终确保它们都完成。所以做一个并等待其回调执行然后执行另一个并等待其回调执行然后执行下一个等等。

  • 更重要的是:我不相信user.pinnedRecipes.remove(foundRecipe)会删除引用。您需要pull [滚动到删除子网站部分]。

然而,您似乎尝试使用MongoDB进行cascade delete。实现此目的的一种方法是使用pre hook。请注意文档中的注意,它只会在您myDoc.remove()时被调用,而不是在您致电MyModel.remove() 时调用。

我相信它会简化您的代码:

RecipeSchema.pre('remove', function (next) {
    var recipe = this;
    // remove recipe comments
    Comment.remove({ _id: { $in: recipe.comments }}, function (err) {
        if (err) {
            return next(err);
        }
        // THEN remove users' recipe references
        User.update({ pinnedRecipes: { $in: [recipe._id] }}, { $pull: recipe._id }, { multi: true }, function (err) {
            if (err) {
                return next(err);
            }
            next();
        });
    });
});



router.delete("/:id", middleware.checkRecipeOwnership, function (req, res) {
    // notice we didn't do Recipe.remove(req.params.id, cb) 
    // b/c Recipe is the model and that would not trigger the hook
    Recipe.findById(req.params.id, function (err, recipe) {
        if (err) {
            return res.redirect("back");
        }
        // this will trigger the hook b/c recipe is a document
        recipe.remove(function (err) {
            if (err) {
                console.log(err);
            }
            res.redirect("/recipes");
        });
    });
});