简体   繁体   English

使用 mongoose 更新 mongoDB 中的子文档

[英]Update a subdocument in mongoDB using mongoose

User Schema用户模式

import mongoose, { Schema, model } from 'mongoose';

const TodoSchema = new Schema({
    task: {
        type: String,
        required: [true, 'Task is required'],
    },
    date: {
        type: Date,
        default: Date.now,
    },
    tags: {
        type: [String],
    },
});

const UserSchema = new Schema({
    name: String,
    googleId: Number,
    date: { type: Date, default: Date.now },
    email: String,
    picture: String,
    todos: {
        type: [TodoSchema],
    },
});
  1. Query the user with (some) googleId使用(一些) googleId查询用户
  2. Find the todo with (todo) _id embedded within todos array查找嵌入在todos数组中的 (todo) _id的 todo
  3. Update that todo properties and return the new todo.更新该 todo 属性并返回新的 todo。

My approach我的方法

const user = await User.findOne({ googleId });
const { todos } = user;

const idx = todos.findIndex((td) => td._id == todoId);

todos[idx].task = task;
todos[idx].tags = tags;

const { todos: updatedTodos } = await user.save();

Problem with my approach我的方法有问题

My approach does work, but it doesn't seem to be an optimal solution as in the case of changing or adding more fields to the todo schema.我的方法确实有效,但它似乎不是一个最佳解决方案,就像在 todo 模式中更改或添加更多字段的情况一样。 While I did consider using spread operator, but that produced new todo id each time the todo is updated虽然我确实考虑过使用扩展运算符,但是每次更新 todo 时都会产生新的 todo id

Question问题

How should I do this using mongoose?我应该如何使用 mongoose 做到这一点?

If you have a Schema for todos, this means that each todo has a unique id in MongoDB.如果你有 todos 的 Schema,这意味着每个 todo 在 MongoDB 中都有一个唯一的 id。 You don't have to filter the todos, in step 2:您不必在步骤 2 中过滤待办事项:

STEP 1:
const user = await User.findOne({ googleId });
const { todos } = user;

STEP 2: // don't do this
const idx = todos.findIndex((td) => td._id == todoId);

STEP 3:
todos[idx].task = task;
todos[idx].tags = tags;

STEP 4:
const { todos: updatedTodos } = await user.save();

Consider this:考虑一下:

  • You already have the todoId which you want to modify您已经有了要修改的 todoId
  • Find if the user exists查找用户是否存在
  • Check if the todo belongs to the user检查待办事项是否属于用户
  • Use findByIdAndUpdate under mongoosefindByIdAndUpdate下使用 findByIdAndUpdate

My suggestion:我的建议:

const todoId = xxxxxxxxx

const user = await User.findOne({googleId})

const orderIdBelongsToUser = user.todos.includes(todoId)
// I'm assuming this is an array of orderIds, otherwise you can decide whether or not to do this check. 
// It seems pretty redundant, if you already have the todo id.

const newTodoObject = {
task: xxxx,
tags: xxxxx
}

if (orderIdBelongsToUser) {
const response = await Todo.findByIdAndUpdate(todoId, newTodoObject)
}

Hope I managed to help.希望我能提供帮助。

Reference: https://mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate参考: https://mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM