node.js - 猫鼬:在 X 集合中创建新元素,在 Y 集合中更新另一个元素
问题描述
我正在尝试开发一个 CRUD 应用程序供用户存储、添加、删除和更新食谱。它建立在 MEVN 堆栈上。由于我需要向用户展示他们创建了哪些食谱,我正在尝试基于此模型创建一个食谱:
const RecipeSchema = new Schema({
title: {
type: String,
required: [true, 'Title of the recipe is required'],
},
category: {
type: Array,
required: [true, 'Category is required'],
},
description: {
type: String,
required: [true, 'Description is required'],
},
imgUrl: {
type: String,
required: [true, 'Image is required'],
},
ingredients: {
type: Array,
required: [true, 'Ingredients are required'],
},
timeOfPreparation: {
type: String,
required: true,
},
preparation: {
type: String,
required: true,
},
sourceName: {
type: String,
required: true,
},
sourceUrl: {
type: String,
required: true,
},
author: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
});
const Recipe = mongoose.model('Recipe', RecipeSchema);
module.exports = Recipe;
同时更新用户模型,基于此:
const UserSchema = Schema({
googleId: String,
name: String,
favorites: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Recipe' }],
authoredRecipes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Recipe' }],
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
在控制器中,我有这个方法(根据@Stock Overflaw 评论):
exports.create_new_recipe = (req, res, next) => {
Recipe.create(req.body)
.then(recipe => {
User.update(
{ _id: req.body.author },
{
$push: { authoredRecipes: recipe.id },
}
);
res.send(res.status);
})
.catch(error => {
res.status(500).json({ error });
});
};
当我转到 /create 端点时会调用此方法。但是,即使我确实获得了所有正确的 ID(req.body.author 和 recipe.id),我也无法让它工作。在我的 mLab 配方集合中,配方正确显示(我使用 authorId 插入的所有数据),但是在用户集合中,authoredRecipes 数组保持为空。
我怎样才能让猫鼬既在一个集合中创建一个对象,又根据它们的 id 更新另一个对象?
解决方案
的文档需要findByIdAndUpdate
该_id
字段作为其值,而不是对象:
User.findByIdAndUpdate(req.body.author, {
$push: { authoredRecipes: recipe.id }
});
// equivalent to the more general method:
User.findOneAndUpdate({ _id: req.body.author }, {
$push: { authoredRecipes: recipe.id }
});
// and if you don't need the modified document in your callback, this should be faster:
// EDIT: this is advised against (we should use a user object, not the collection)
User.update({ _id: req.body.author }, { // or updateOne
$push: { authoredRecipes: recipe.id }
});
编辑:一个工作的,最小的例子
介意{new: true}
吗?取决于你如何测试它是否有效......
const mongoose = require('mongoose');
const fs = require('fs');
const userIdFile = './tmp.txt'; // just for this test
mongoose.connect('mongodb://localhost/meuh', {
useNewUrlParser: true, // removes a deprecation warning
useFindAndModify: false // removes another deprecation warning
});
// make schemas/models
const RecipeSchema = mongoose.Schema({
title: { type: mongoose.Schema.Types.String }
});
const UserSchema = mongoose.Schema({
name: { type: mongoose.Schema.Types.String },
data: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Recipe' }]
});
const RecipeModel = mongoose.model('Recipe', RecipeSchema);
const UserModel = mongoose.model('User', UserSchema);
// user precreation
// UserModel.create({
// name: 'me, myself and I'
// }).then((user) => {
// fs.writeFile(userIdFile, user.id, console.log.bind(null, 'error writing file:'));
// mongoose.connection.close();
// });
// return;
// fetch user
const userId = fs.readFileSync(userIdFile);
let pushedRecipeId; // to test everything went smooth
RecipeModel.create({
title: 'pasta solo'
}).then((recipe) => {
console.log('created recipe:', recipe);
pushedRecipeId = recipe.id;
return UserModel.findOneAndUpdate(
{ _id: userId },
{ $push: { data: recipe.id } },
{ new: true } // forces callback to be passed a fresh object
);
}).then((user) => {
console.log('updated user:', user);
console.log('izok:', !!~user.data.indexOf(pushedRecipeId));
mongoose.connection.close();
}).catch((err) => {
console.log('error', err);
mongoose.connection.close();
})
我得到的示例输出:
# creating user (uncommented this part)
ubuntu@ubuntu-VirtualBox:~/web/test$ node .
error writing file: null
# calling for $push (re-commented user creation)
ubuntu@ubuntu-VirtualBox:~/web/test$ node .
created recipe: { _id: 5c72be7032bd2f1acad37c95, title: 'pasta solo', __v: 0 }
updated user: { data: [ 5c72be7032bd2f1acad37c95 ],
_id: 5c72be6a8143fd1aa9416d85,
name: 'me, myself and I',
__v: 0 }
izok: true
# again $push
ubuntu@ubuntu-VirtualBox:~/web/test$ node .
created recipe: { _id: 5c72c020c2ac7a1b8c65fa36, title: 'pasta solo', __v: 0 }
updated user: { data: [ 5c72be7032bd2f1acad37c95, 5c72c020c2ac7a1b8c65fa36 ],
_id: 5c72be6a8143fd1aa9416d85,
name: 'me, myself and I',
__v: 0 }
izok: true
# and again
ubuntu@ubuntu-VirtualBox:~/web/test$ node .
created recipe: { _id: 5c72c023bf62331b97ef096b, title: 'pasta solo', __v: 0 }
updated user: { data:
[ 5c72be7032bd2f1acad37c95,
5c72c020c2ac7a1b8c65fa36,
5c72c023bf62331b97ef096b ],
_id: 5c72be6a8143fd1aa9416d85,
name: 'me, myself and I',
__v: 0 }
izok: true
# end
ubuntu@ubuntu-VirtualBox:~/web/test$
我看不出你的代码有什么问题,但至少你有一些东西可以比较......希望这会有所帮助!
推荐阅读
- c# - 通过 ASP.NET Core 2.2 在 Windows Server 2016 中无头 Google Chrome 不会触发
- azure - 如何在 azure 上找到我的 ubuntu vm 的带宽?
- html - Django:html不使用块内容显示表单
- css - Bootstrap如何避免最小宽度的列中断
- smartcontracts - 创建 abi 和 wsm 文件后,如何使用 SET 在测试网上的 EOS 中部署智能合约?
- go - 带有 go 的 Twitter 机器人在 Heroku 中崩溃
- css - Style Prime-ng dropdown child elements
- python - [Windows,python]如何让subprocee.Popen()启动的进程在父进程死亡时自动终止?
- java - Android:当 ImageView 没有图像时,防止进入下一个活动
- php - mysql上基于引导徽章颜色的数据