Node.js mongoose:在X集合中创建新元素,在Y集合中更新另一个元素

Node.js mongoose:在X集合中创建新元素,在Y集合中更新另一个元素,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我正在尝试开发一个CRUD应用程序,供用户存储、添加、删除和更新食谱。它建立在MEVN堆栈上。由于我需要向用户展示他们创建的配方,因此我尝试基于此模型创建一个配方: const RecipeSchema = new Schema({ title: { type: String, required: [true, 'Title of the recipe is required'], }, category: { type:

我正在尝试开发一个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 Overlaw注释):

})

在转到/创建端点时调用此方法。然而,即使我得到了所有正确的id(req.body.author和recipe.id),我也无法让它工作。在我的mLab配方集合中,配方显示正确(我使用authorId插入的所有数据),但是在用户集合中,authoredRecipes数组保持为空

如何让mongoose既在一个集合中创建一个对象,又根据其id更新另一个对象?

for
findbyiandupdate
需要
\u 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();
})
我得到的示例输出:

#创建用户(未注释此部分)
ubuntu@ubuntu-VirtualBox:~/web/test$节点。
写入文件时出错:null
#调用$push(重新评论用户创建)
ubuntu@ubuntu-VirtualBox:~/web/test$节点。
创建的配方:{uu id:5c72be7032bd2f1acad37c95,标题:“意大利面独奏”,uuu v:0}
更新的用户:{数据:[5c72be7032bd2f1acad37c95],
_id:5c72be6a8143fd1aa9416d85,
名字:“我,我自己和我”,
__v:0}
伊佐克:是的
#再推一次$push
ubuntu@ubuntu-VirtualBox:~/web/test$节点。
创建的配方:{id:5c72c020c2ac7a1b8c65fa36,标题:'意大利面独奏',{v:0}
更新用户:{数据:[5c72be7032bd2f1acad37c95,5c72c020c2ac7a1b8c65fa36],
_id:5c72be6a8143fd1aa9416d85,
名字:“我,我自己和我”,
__v:0}
伊佐克:是的
#再三
ubuntu@ubuntu-VirtualBox:~/web/test$节点。
创建的菜谱:{id:5c72c023bf62331b97ef096b,标题:'意大利面独奏',{v:0}
更新的用户:{数据:
[5c72be7032bd2f1acad37c95,
5c72c020c2ac7a1b8c65fa36,
5c72c023bf62331b97ef096b],
_id:5c72be6a8143fd1aa9416d85,
名字:“我,我自己和我”,
__v:0}
伊佐克:是的
#结束
ubuntu@ubuntu-VirtualBox:~/web/test$

我看不出你的代码有什么问题,但至少你有一些东西可以比较。。。希望这有帮助

不幸的是,这并不能解决这个问题,我仍然没有收到任何来自authoredRecipes的回复array@llievredemars我更新了一个例子,希望你能找出问题所在。谢谢!我插入了{new:true},这就解决了这个问题!我很感激你花时间调试这个:)祝你有一个很棒的一天!好东西!但这意味着您没有完全测试数组是否为空:在回调中它只是空的(实际上:每次都晚了一步),而DB已经存储了它
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();
})