如何同时修改多个Mongoose集合?

xmd2e60i  于 2023-11-19  发布在  Go
关注(0)|答案(1)|浏览(148)

我有3 Mongoose 收集:董事会,线程和答复。每个答复属于1线程(作为一个数组的项目在“答复”属性),每个线程属于1董事会(作为一个数组的项目在“线程”属性)。
正如下面的代码,每当我想通过发送帖子请求向数据库添加一个新的回复时,我必须更新所有3个集合:Board,Thread和Reply。
有没有其他的方法来实现这一点,而不必手动修改每个集合一个接一个?

app.route('/api/replies/:board').post(async (req, res) => {
    const { text, delete_password, thread_id } = req.body;
    const board = req.params.board;
    
    if (!thread_id.match(/^[0-9a-fA-F]{24}$/)) {
      res.send('Thread ID is invalid');
    } else {
      const updateBoard = await BoardModel.findOne({name: board}).exec(); //find the Board in Board collection
      const updateThread = updateBoard.threads.id(thread_id); //find the Thread in that Board
      const updateThreadDB = await ThreadModel.findById(thread_id).exec(); //find the Thread in Thread collection
      if (!updateThreadDB || !updateBoard) {
        res.send("Board or thread not found");
      } else {
        //Add new Reply
        const newReply = new ReplyModel({
          text: text,
          delete_password: delete_password,
          reported: false,
        })
        let saveReply = await newReply.save(); //save Reply to Reply collection

        //Update Thread and Board
        updateThreadDB.replies.push(saveReply);
        updateThread.replies.push(saveReply);
        let saveBoard = await updateBoard.save(); //update new Board collection
        let saveThread = await updateThreadDB.save(); //update new Thread collection

        res.json(saveReply);
      }
    }
  })

字符串
这是我的模型文件:

const mongoose = require('mongoose');
mongoose.connect(process.env.DB);
const { Schema } = mongoose;

const replySchema = new Schema ({
  text: {type: String, required: true},
  created_on: {type : Date, required: true, default: () => { return new Date() }},
  delete_password: {type: String, required: true},
  reported: {type: Boolean, required: true},
})
const Reply = mongoose.model('Reply', replySchema);

const threadSchema = new Schema ({
  text: {type: String, required: true},
  created_on: {type : Date, required: true, default: () => { return new Date() }},
  bumped_on: {type : Date, required: true, default: () => { return new Date() }},
  reported: {type: Boolean, required: true},
  delete_password: {type: String, required: true},
  replies: {type: [replySchema], required: true},
});
const Thread = mongoose.model('Thread', threadSchema);

const boardSchema = new Schema ({
  name: {type: String, required: true},
  threads: {type: [threadSchema], required: true},
});
const Board = mongoose.model('Board', boardSchema);

exports.Board = Board;
exports.Thread = Thread;
exports.Reply = Reply;

368yc8dk

368yc8dk1#

看看你的模式和你存储数据的方式,你似乎在复制数据。例如,你在replies集合中创建了一个新的Reply

let saveReply = await newReply.save();

字符串
然后,您将相同的数据添加两次。一次添加到threads集合中的threds.replies数组,然后一次添加到boards集合中的boards.threads数组:

updateThreadDB.replies.push(saveReply);
updateThread.replies.push(saveReply);
let saveBoard = await updateBoard.save();
let saveThread = await updateThreadDB.save();


Mogodb文档的大小限制为16MB,因此如果您的应用程序很受欢迎,您最终可能会超过每个boards文档的大小,将所有这些threads和嵌套的replies存储在单个文档中。
您需要使用两个东西,referenced documents和Model.findByIdAndUpdate()。
你可以像这样更新你的模式:

const boardSchema = new Schema ({
   name: {
      type: String, 
      required: true
   },
   threads: {
      type: mongoose.Types.ObjectId, //< Store the _id of the thread
      ref: 'Thread', //< This will reference the threads collection
   },
});

const threadSchema = new Schema ({
   text: {
      type: String, 
      required: true
   },
   //...
   replies: {
      type: mongoose.Types.ObjectId, //< Store the _id of the reply
      ref: 'Reply', //< This will reference the replies collection
   },
});


现在,当您创建Thread时,您只需要将Thread_id(即ObjectId)推入Board.threads一次
然后,当您创建Reply时,您只需将Reply_id(即ObjectId)推入Thread.replies一次
下面是一个如何为Board创建新Thread的示例:

//Get the board _id
const boardId = req.params.board;

//Create a new Thread. Use create() instead of new and .save()
const thread = await Thread.create({
   text: req.body.text,
   //...
});

// Add the thread._id ObjectId into the board.threads array. 
// I have used findByIdAndUpdate() for demonstration 
const board = await Board.findByIdAndUpdate(boardId,
   { $push: { threads: thread._id } },
   { new: true }
);


现在,您不需要再次触摸Board文档,直到您需要删除Thread
以下是如何创建回复的示例:

//Get the thread _id
const threadId = req.params.thread;

//Create a new Reply. Use create() instead of new and .save()
const reply = await Reply.create({
   text: req.body.text,
   //...
});

// Add the reply._id ObjectId into the thread.replies array. 
// I have used findByIdAndUpdate() for demonstration 
const thread = await Thread.findByIdAndUpdate(threadId,
   { $push: { replies: reply._id } },
   { new: true }
);


请注意,我不需要去获取Board父文档。现在您可以创建任意多个回复,只需将每个回复的_id推送到父线程中。这将节省保存大量空间,因为只有ObjectId存储在Thread中,只有ObjectId存储在每个Board中。
最后,如果你想获得每个引用的文档,你可以使用populate。请阅读它以了解,但这里是一个如何做到这一点的示例:

//Get the board _id
const boardId = req.params.board;

const board = await Board.findById(boardId)
.populate({
    path: 'threads', //< Replace all ObjectIds with the actual Thread document
    model: Thread,
    populate: {
        path: 'replies', //< Within each Thread replace all ObjectIds with the actual Reply document
        model: Reply
    },
});

相关问题